2011-12-14 62 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才能得到正確的結果。