2

I want to do right shift of 33 on a 32 variable and store the result into a float variable.

For suppose, the value is 1717986812. When we right shift by 33, we expect the value to be 0.2.

But when I do 1717986812 / (1<<33), I am getting some other huge integer value. I know that the result of 1<<33 can't be stored in a 32-bit value. So, I tried 17917986812 / (1UL<<33), but didn't get the correct results. I believe, something needs to be done regarding format conversions. But, couldn't figure it out.

rkc
  • 111
  • 8
  • 3
    The result of shifting a 32-bit integer by more than 32 bits is undefined. – Weather Vane Mar 31 '20 at 14:18
  • 1
    *For suppose, the value is 1717986812. When we right shift by 33, we expect the value to be 0.2.* What do you base that on? Right-shifting the `signed int` value `1717986812` any number of places is an `int` that cannot have a value of `0.2`, even assuming it's wide enough to be shifted 33 places. – Andrew Henle Mar 31 '20 at 14:19
  • Confirm you actually want to divide by 2^33 – Jabberwocky Mar 31 '20 at 14:49
  • 2
    C11 [§6.5.7 Bitwise shift operators ¶3](http://port70.net/~nsz/c/c11/n1570.html#6.5.7p3): _The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined._. Right shifting a 32-bit integer by 32 or more places is undefined behaviour — the result is not predictable (and is not automatically zero). – Jonathan Leffler Mar 31 '20 at 16:07

1 Answers1

7

For suppose, the value is 1717986812. When we right shift by 33, we expect the value to be 0.2.

Wait wait? No? Bit shifting is an integer activity, so a floating-point result to appear would be very magical. Shifting an integer right by more bits that the entire integer consists of, would "logically" result in 0, but in C it happens to be undefined.

If you want to divide a floating point value, just do so:

float x = 1717986812;
x /= powf(2, 33);
printf("got %g\n", x);

This printed 0.2 when I tested it online.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 1
    Consider `x /= powf(2, 33)` → `x /= 0x1p33f`, `x *= 0x1p-33f`, or `x = ldexpf(x, -33)`. – Eric Postpischil Apr 01 '20 at 02:26
  • @EricPostpischil For sure, I was kind of trying to be overly clear (and semi-hoping for this to be something a compiler can pick up, too). – unwind Apr 03 '20 at 09:07