Reputation: 4695
Given what we know about floating point precision, why does this code:
float a = 0.1f;
System.out.println(a);
Print 0.1
and not 0.100000001
?
Upvotes: 2
Views: 624
Reputation: 281757
0.100000001
wouldn't be exact either. If Java were to print this float completely unrounded, it would print
0.100000001490116119384765625
which is unuseful for most floating-point use cases.
Either it doesn't round at all and you get 0.100000001490116119384765625
, or it rounds, and you need a rounding strategy. The rounding strategy they picked is to print exactly enough digits after the decimal point to distinguish the float from any other float value, with a minimum of one digit. It is not necessarily enough to distinguish the float from any other double value.
Upvotes: 8
Reputation: 159165
The println(a)
call to ends up calling Float.toString(a)
, which says:
How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type
float
. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument f. Then f must be thefloat
value nearest to x; or, if twofloat
values are equally close to x, then f must be one of them and the least significant bit of the significand of f must be0
.
Or said another way, since a IEEE 754 single-precision floating-point value only has from 6 to 9 significant decimal digits precision, it won't include that final 1
, since it exceeds the precision of the stored value.
Here is code to show the numbers:
System.out.println(Math.nextDown(0.1f)); // prints: 0.099999994
System.out.println(0.1f); // prints: 0.1
System.out.printf("%.15f%n", 0.1f); // prints: 0.100000001490116
System.out.println(Math.nextUp(0.1f)); // prints: 0.10000001
Upvotes: 8