Search code examples
c++bit-shift

c++ bit shifting a float


float length =  32.32f;
long  i = *(long*)&length ; // casting a float pointer to a long pointer...
i >>= 1; // right shift i but 1 ... or div by 2
length = *(float*)&i; // is this necessary?

Printing length gives: 0.0

The end result should be: 16.16;

This idea is from http://en.wikipedia.org/wiki/Fast_inverse_square_root. Im trying to understand the section of the code were the long in a float is taken out and bitwise operations are performed on it. Im guessing the point is to improve performance by avoiding branching?

The above code fails. Can anyone tell me what im doing wrong? I was under the impression that it was as simple as getting the long storage in a float and manipulation it, is this wrong?

i found something interesting, if i change the code to:

 float length =  32.32f;
 long  i = *(long*)&length ;
 i  = 0x5f3759df - ( i >> 1 ); 
 length = *(float*)&i;

adding this number (0x5f3759df) to the mix.

Printing out length*100 gives : 17.0538 // approximation of 16.16
trying it with different length gives the same results.

eg: length = 100; result is : 10.3299?? // almost...


Solution

  • The binary of 32.32f is 01000010000000010100011110101110.

    After shift: 00100001000000001010001111010111

    You can see how float numbers is stored from Wikipedia.

    sign:0

    exp:01000010=66

    mantissa:00000001010001111010111=2-7(around)

    So the result = 2(66-127)*(1+2-7)=2-59(around)

    It's not zero. If you use printf("%.40f\n",x2); then you will see it.

    If you feel strange about why that magic numbers works: you can read the wiki page carefully or read this paper.