In cpp in android, I found that casting long to float resulting a wrong value:
long m = 1553138135;
float n = m;
dmLogInfo(“gwjgwj,pi=%f”, n);
In this example, I got the following log:
![]()
What’s wrong?
BTW, what compiler used for android?
In cpp in android, I found that casting long to float resulting a wrong value:
long m = 1553138135;
float n = m;
dmLogInfo(“gwjgwj,pi=%f”, n);
In this example, I got the following log:
![]()
What’s wrong?
BTW, what compiler used for android?
Try this?
The same.
long m = 1553138135L;
float n = m;
dmLogInfo(“gwjgwj,sizeof(float)=%d,m=%ld,n=%f”, sizeof(float), m, n);
![]()
I have tried double, it is correct, but when casting double to float, it is wrong again.
I have tried in VS, the same result, so this is the limitation of float precision
Maybe @Mathias_Westerdahl would have input.
We have the details documented about compilers.
This is a case of floating point precision. Both single and double precision floating point numbers have them.
When it comes to floating point precision, there are a lot of details here
A uint32_t has 32 bits, and can store all the numbers between [0,4294967296] or 0 - 2^32
An int32_t also has 32 bits, can store all the numbers between [-2147483648,2147483647]. The Most Significant Bit is used to store the sign.
A single precision float has 32 bits (format IEEE 754) and spans the range [1.2E-38, 3.4E+38]
Also 3.4E+38 is way larger than 2147483647, so how does a float manage to store that into 32 bits.
While the int32_t can represent all numbers in its range, the float has to also somehow store decimals.
As you can imagine, there is a tradeoff and it’s with regards to precision.
The 32 bits are divided like so:
These bits represent the power-of-two exponent, or the range of numbers represented. Or perhaps a sliding window
E.g. [0.5,1], [1,2], [2,4], [4,8], [8,16] and so on
Once you’ve found your range, e.g. [2,4], the floating point divides that by 2^23 = 8388608
(4 - 2) / 8388608 = 0.0000002384185791
This means that the precision in the range [2,4] is 0.0000002384185791. That is, the step between two consecutive floats is 0.0000002384185791.
For the range [8192,16384] the precision is
(16384 - 8192) / 8388608 = 0,0009765625
Fabien Sanglard does an excellent explanation
This is a big number.
The range for 1553138135 is [2^30,2^31] = [1073741824, 2147483648] (log2(1553138135) ~= 30.53)
You might notice that you’re having an upper limit in your range of 2^31. That’s almost the upper limit for unsigned integers!
But, as we mentioned, the upper limit of a single float precision number is 3.4E+38, so we’re good.
The precision, between consecutive valid floats, is calculated again:
(2147483648 - 1073741824) / 8388608 = 128
So, in that range the the difference between two consecutive floats is 128.
Your number 1553138135 is not evenly divisible by 128:
(1553138135 - 1073741824) / 128 = 3745283,6796875
Rounding that number to 3745284 and convert back:
3745284 * 128 + 1073741824 = 1553138176
Et voilà, 1553138176 is the number you got.
Whoa!! I hadn’t even imagined that floating point arthimetic happened like this.
Yeah, it’s good to know about at least.
For instance, in shaders, the lowp, mediump and highp all control the number of bits for the entire floating point number. Less bits -> bigger precision steps between numbers -> more jitter.