为什么这个精度失败的例子显示双精度而不是浮点数?

Ale*_*scu 0 java floating-point double floating-point-precision

还有,为什么浮点不应使用货币的操作和可爱的例子给出的SO的大讨论在这里从Bloch的Effective Java的.

我正在玩这个,发现一些奇怪的东西.如果数字是双倍的:

System.out.println(1.03d - .42d); 
//prints out 0.6100000000000001.
Run Code Online (Sandbox Code Playgroud)

但是,如果数字是浮点数:

System.out.println(1.03f - .42f); 
//prints out 0.61.
Run Code Online (Sandbox Code Playgroud)

为什么这对浮子也不会以同样的方式失败?两种类型都容易出现同样的问题,但是导致行为差异的原因是什么?

Jon*_*eet 5

这里涉及八个有趣的值(每种类型四个).他们的确切价值是:

双值

1.03d:  1.0300000000000000266453525910037569701671600341796875
0.42d:  0.419999999999999984456877655247808434069156646728515625
Result: 0.6100000000000000976996261670137755572795867919921875
0.61d:  0.60999999999999998667732370449812151491641998291015625
Run Code Online (Sandbox Code Playgroud)

浮动值

1.03f:  1.0299999713897705078125
0.42f:  0.4199999868869781494140625
Result: 0.61000001430511474609375
0.61f:  0.61000001430511474609375
Run Code Online (Sandbox Code Playgroud)

注意如何最接近的double1.03略比1.03,与最接近的一倍,达到0.42略小于 0.42 ...这样的减法的结果由这两个误差之和与精确(十进制)减法不同.

最接近float1.03且最接近float0.42都小于原始值,因此错误在某种程度上相互抵消.这就是double结果"感觉"比float结果更不准确的原因.该float结果正好是接近0.61,你可以表示为float,所以字符串表示仅仅是"0.61".因为仔细double比相减结果,以0.61,字符串表示具有两个之间进行区分.