关于为什么浮点不应该用于货币操作的问题有一个很好的讨论,并且Bloch的Effective Java给出了一个可爱的例子here。
我正在玩这个并注意到一些奇怪的东西。如果数字是双倍的:
System.out.println(1.03d - .42d);
//prints out 0.6100000000000001.
但是,如果数字是浮点数:
System.out.println(1.03f - .42f);
//prints out 0.61.
为什么浮子也不会以同样的方式失败?两种类型都容易出现同样的问题,但是导致行为差异的原因是什么?
答案 0 :(得分:5)
这里涉及八个有趣的值(每种类型四个)。他们的确切值是:
双倍值
1.03d: 1.0300000000000000266453525910037569701671600341796875
0.42d: 0.419999999999999984456877655247808434069156646728515625
Result: 0.6100000000000000976996261670137755572795867919921875
0.61d: 0.60999999999999998667732370449812151491641998291015625
浮动值
1.03f: 1.0299999713897705078125
0.42f: 0.4199999868869781494140625
Result: 0.61000001430511474609375
0.61f: 0.61000001430511474609375
请注意,最接近的double
到1.03是如何更多而不是1.03,而最接近的0.42是少而不是0.42 ...所以减法的结果与精确(十进制)减法的差别在于这两个误差的总和。
最接近的float
到1.03,最接近的float
到0.42都小于原始值,因此错误会在某种程度上相互抵消。这就是double
结果“感觉”比float
结果更不准确的原因。 float
结果恰好接近0.61,因为您可以表示为float
,因此字符串表示只是“0.61”。由于 比减法结果更接近double
到0.61,因此字符串表示必须区分两者。