可能重复:
Floating point arithmetic not producing exact results in Java
我正在做这个简单的分工,但我得到一个非常奇怪的输出:
double a = 60/(1.2-1.1);
a => 600.0000000000008
什么时候应该是600。
提前致谢
答案 0 :(得分:8)
在IEEE-754二进制双精度中,我们需要考虑二进制表示中的1.1和1.2:
1.2 = 0b1.001100110011001100110011001100110011001100110011001100110011...
1.1 = 0b1.000110011001100110011001100110011001100110011001100110011001...
请注意,我们需要无限多位来完全用二进制表示它们。 double只有53位的重要性,我们必须砍掉这些数字:
1.2 = 0b1.001100110011001100110011001100110011001100110011001100110011...
1.1 = 0b1.000110011001100110011001100110011001100110011001100110011001...
^ round from here
==>
1.2 ~ 0b1.0011001100110011001100110011001100110011001100110011
(= exactly 1.1999999999999999555910790149937383830547332763671875)
1.1 ~ 0b1.0001100110011001100110011001100110011001100110011010
(= exactly 1.100000000000000088817841970012523233890533447265625)
因此1.2 - 1.1是:
1.2 ~ 0b1.0011001100110011001100110011001100110011001100110011
- 1.1 ~ 0b1.0001100110011001100110011001100110011001100110011010
————————————————————————————————————————————————————————————————
0b0.00011001100110011001100110011001100110011001100110010000
(= exactly 0.09999999999999986677323704498121514916419982910156250000)
我们实际上可以准确计算60 / 0.0999999999999998667732370449812151491641998291015625,这给出了
600.0000000000007993605777301137740672368493927467455286920109359612256820927...
^ 16th significant figure
匹配OP的
结果600.0000000000008
答案 1 :(得分:5)
因为double
原语是floating point数据类型,它可以交换精度以保存更大范围的值。
如果您需要任意精确度,则应使用BigDecimal代替。
答案 2 :(得分:4)
你已经发现了浮点运算的奇迹。由于数字的内部表示是二进制的,因此无法精确表示某些十进制数。因此,某些算术运算会在最低有效数字中产生意外结果。
例如,在数值方法课程中详细介绍了这一点,但Wikipedia article并不错。
答案 3 :(得分:2)
您可能应该阅读"What Every Computer Scientist Should Know About Floating-Point Arithmetic"。
简而言之,并非所有真实值都可以用double,
精确表示,因此在需要确切答案时应避免使用它们。
答案 4 :(得分:2)
您应该使用 BigDecimal 来获得正确的结果。
答案 5 :(得分:1)
这不是一个“四舍五入的问题”。某些数字不能用二进制浮点精确表示。就像1/3不能用十进制精确表示,因为没有人有无限的纸张供应。 (或位)。