float x = 0.98123452f;
System.out.println(x); //it prints out 0.9812345
float x = 0.98123453f;
System.out.println(x); //it prints out 0.98123455
I have no idea why the second one's output is 0.98123455 instead of 0.9812345. Isn't the precision of float is 7 decimal digits?
To see the exact value of your float, you can use a BigDecimal:
float x = 0.98123452f; System.out.println(new BigDecimal(x));
which outputs:
0.981234490871429443359375
So technically, this float:
float x = 0.981234490871429443359375f; System.out.println(new BigDecimal(x)); //prints 0.981234490871429443359375
has 24 digits precision (it was obviously cherry-picked)...
Forget what is above: BigDecimal only has a double constructor so there was a cast to double and the logic above is flawed.
Bottom line: not all numbers can be represented as a float and the gap between one float and the next one varies depending on the magnitude of the number.
The IEEE 754 float representation of
0.98123453
is 32 bits of (sign, exp, mantissa):
0 01111110 11110110011001000110000
which is:
0.9812345504760742
in double precision, and cast back to float decimal representation:
0.98123455
The number of bits allocated to a single precision (float) is 32, and 64 bits for double precision. Further note that BigDecimal
that is frequently suggested will store your number as a string, and not in IEEE754 format. It will do a conversion when it needs to act on the number, and while it has a better precision, it is awfully slow.
EDIT. To clarify why it prints 0.98123455, we need to observe that it is the closest single precision representation of the number 0.98123453:
00111111011110110011001000101111 = 0.9812345 (sp) = 0.9812344908714294 (dp)
00111111011110110011001000110000 = 0.98123455 (sp) = 0.9812345504760742 (dp)
00111111011110110011001000110001 = 0.9812346 (sp) = 0.981234610080719 (dp)
sp = single precision, dp = double precision
The listing is for the [-1,+1] binary range around the number, and you can see that 0.98123453
is closest to the 10000
suffix of the mantissa, while 0.98123452
is closest to the 01111
suffix.
isn't the precision of float is 7 decimal digits?
No. It is 23 binary digits. The minimum number of decimal digits that can be represented in 23 bits is therefore 6. This is not a mere 'guarantee' as stated in other answers here, it is a mathematical tautology arising from log10(2^23) = 6.92369.
The default output format for floating-point in Java is to print just enough digits so that conversion back to the floating-point type produces the original value.
What happens in detail in your code is:
0.98123452f
is converted to the float
value 0.981234490871429443359375. float
value to 0.9812345 is 0.981234490871429443359375. However, converting “0.981234” to float
would produce 0.981234014034271240234375, so the “5” is needed. 0.98123453f
is converted to the float
value 0.98123455047607421875. An interesting consequence of this is that, if you assign a float
value to a double
object and then print the double
value, it will often display more digits than printing the float
value, even though the values are exactly the same. Because the double
format is finer (more precise) than the float
format, there may be many double
values between the value printed for float
(eg 0.9812345) and the actual value (0.981234490871429443359375). Therefore, more digits are needed to distinguish the value.
不, float
只有六位数的十进制精度。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.