The Java specification requires this imperfect display of values. The f
format produces only as many significant digits as the Double.toString(double)
method would produce and then mindlessy appends zeros to get to the requested precision.
Per the documentation, for the f
format, if the precision exceeds the number of digits after the decimal point that Double.toString(double)
would produce, then “zeros may be appended to reach the precision.” This does not state what those zeros are appended to. Presumably, they are appended to the string that Double.toString(double)
would produce.
The documentation for Double.toString(double)
says it produces “as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double
.” I discuss that further here. For 0.1000000000000000055511151231257827021181583404541015625, Double.toString(double)
produces “0.1”. (The neighboring values, 0.09999999999999999167332731531132594682276248931884765625 and
0.10000000000000001942890293094023945741355419158935546875, are both further from .1 than 0.1000000000000000055511151231257827021181583404541015625 is, and they are formatted as “0.09999999999999999” and “0.10000000000000002”, so “0.1” serves to uniquely distinguish 0.1000000000000000055511151231257827021181583404541015625 from its neighbors.)
Thus, System.out.println(String.format("double 0.1= %.30f", d))
starts with the “0.1” from Double.toString(double)
and appends 29 zeroes.
Similarly, if you change d
to 0.09999999999999999167332731531132594682276248931884765625, String.format
produces “0.099999999999999990000000000000”—it has taken the toString
result and appended zeros. And for 0.10000000000000001942890293094023945741355419158935546875 it produces “0.100000000000000020000000000000”.
This conforms to the specification. The specified behavior is incapable of presenting the true value correctly, so I regard the specification as defective.
Incidentally, the Java specification is troublesome whether the requested precision is greater than or less than the number of digits that Double.toString(double)
would produce. In the case when the request permission is less, the Java specification requires a double rounding that can increase errors.