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...
If you really want to bit-shift a float, you could use a method called fixed-point. Say you want to hold the number 1.23 (and bit-shift it later). You would store 123 in an int, and every time you accessed the variable you would divide the value by 100:
See this answer for more information. Shifting floats makes no sense since it's represented as the concatenation of a sign bit, an exponent and a mantissa. Since shifting operation is about shifting bits, it would imply shifting bits from mantissa to exponent and / or to sign bit.
In C++, bit shift operators do what their names suggest, shifting bits. According to the program’s requirements, a bitwise shift operator shifts the binary bits left or right.
You can't left shift float variables, because (a) your FPU generally will not have a barrel shifter exposed to you so physically cannot generate code to do that, and (b) what would it even mean? The underlying bit representation consists of multiple fields with different meanings, do you really want those bits bleeding into each other?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With