2011-12-14 90 views
2

可能重复:
Floating point arithmetic not producing exact results in JavaJava的双变量具有奇特值

我这样做简单的除法,但我得到一个非常奇怪的输出:

double a = 60/(1.2-1.1); 

A = > 600.0000000000008

当它应该是事先

+0

请尝试为分母创建第二个双变量:double b = 1.2-1。1;双a = 60/b;同样的结果? – 2011-12-14 20:40:09

+1

你应该[接受](http://meta.stackexchange.com/q/5234/161469)你以前的答案 – amit 2011-12-14 20:46:39

+0

第二次这个问题是今天问的,只是在Java标签。必须是“如何解析日期”的最常见问题。 – 2011-12-14 20:47:06

回答

8

在IEEE-754二进制双,我们需要考虑1.1和1.2的二进制表示:

1.2 = 0b1.001100110011001100110011001100110011001100110011001100110011... 
1.1 = 0b1.000110011001100110011001100110011001100110011001100110011001... 

注意,我们需要无穷多个位准确地表示他们的二进制文件。双只具有意义的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 
5

得益于由于double原始是交易精度保持较大的值的范围的能力的floating point数据类型。

如果你需要任意的精度,你应该使用BigDecimal来代替。

4

你已经发现了浮点运算的奇迹。由于数字的内部表示是二进制的,因此某些十进制数不能精确表示。因此,一些算术运算会给最不重要的数字带来意想不到的结果。

这包含在例如数值方法课程中的细节中,但Wikipedia article并不差。

1

这不完全是一个“舍入问题”。某些数字不能用二进制浮点正确表示。就像1/3不能完全用十进制表示,因为没有人有无限的纸张供应。 (或比特)。

2

您应该使用BigDecimal才能得到正确的结果。