0

I have a calculation which is the following:

1472 / 48 = 30.666667
(30 * 48) = 1440
(0.666667 * 48) = 32

So the numbers I nead are 1440 and 32, which can be calculated with the real part and the fractional part of the first calculation. Using the following piece of code I find the real part, but the fractional part is on a scale.

#define SHIFT_AMOUNT    16
// 2 bytes is used to map divisions
#define SCALE_FACTOR    65535 // (2^16)
#define SHIFT_MASK      ((1 << SHIFT_AMOUNT) - 1)

uint32_t total_msgs = DATA_LENGTH << SHIFT_AMOUNT;
total_msgs /= PAYLOAD_SIZE;

uint8_t real_part = total_msgs >> SHIFT_AMOUNT; // 30
uint32_t decimal_part = total_msgs & SHIFT_MASK; // 43690

Now for the last calculation I'm stuck. How do I get 32 from 43690 (which really is ((43690 / 65535) = 0.666667) ?

boortmans
  • 1,138
  • 2
  • 24
  • 40

2 Answers2

2

The usual way to solve this problem is the % operator:

quotient = DATA_LENGTH / PAYLOAD_SIZE;
fraction = DATA_LENGTH % PAYLOAD_SIZE;
rici
  • 234,347
  • 28
  • 237
  • 341
  • On some badly optimising compilers this may result in true divisions. – too honest for this site May 01 '17 at 20:36
  • I didn't think this was possible.. Thanks, fixed it! – boortmans May 01 '17 at 20:37
  • @olaf: that is true. On the other hand, if `PAYLOAD_SIZE` is a constant, a good compiler may use no divisions; you could manually insert the equivalent code if it were critical. – rici May 01 '17 at 20:41
  • @rici: Shifting is fine. Typically such operations are wrapped in `inline` functions in a library to handle fixed-point operations. The shift-factor is often passed as argument ("binary point"), which makes shifts in fact more useful than divisons. But I'm not clear if that is what OP really wants; not sure if he knows himself actually. – too honest for this site May 01 '17 at 20:48
  • Given how OP reacted to this, I suspect that the fixed-point thing was an XY-problem in the first place.. but who knows, @boortmans please come back and clarify. – harold May 01 '17 at 20:53
  • It is a xy problem indeed. I wanted to compute the rest from a division and the print statement returned the real part only. therefore I came to fixed point arithmetic, but given the modulo answer, i found it is possible with % aswell – boortmans May 01 '17 at 21:09
1

As others have mentioned, since the values you need are the integer part of the quotient and the remainder from division, you can use the / and % operators respectively to do that:

int quot = 1472 / 48;
int rem = 1472 % 48;

However, rather that doing two separate operations with the same pair of numbers, you can use the div function:

div_t result = div(1472, 48);
printf("quotient=%d, remainder=%d\n", result.quot, result.rem);

If you're performing this particular computation often, this might give you a speed increase as some processors (x86 in particular) give you both values with a single instruction, so it could potentially cut the number of division operations in half.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    I would hope the compiler merges those operations anyway (GCC and Clang would), can't hurt to make it explicit of course – harold May 01 '17 at 20:50