2013-03-28 53 views
7

任何人都可以解釋爲什麼地球上這些「相同」的表達式返回不同的值?Android:java四捨五入錯誤。不明白爲什麼?

(new BigDecimal(String.valueOf(131.7d))).multiply(new BigDecimal(String.valueOf(0.95d))).doubleValue() = 125.115 

(new BigDecimal(    131.7d)).multiply(new BigDecimal(    0.95d)).doubleValue() = 125.11499999999998 

BigDecimal在做什麼不同?

+1

對於那些投票結束爲重複,那些問題是相似的,但不重複。 – Woot4Moo

回答

5

如果您閱讀API文檔,您會發現使用Double.toString(double)來設置值的格式爲String.valueOf(dobule)。這也許並不明顯,但Double.toString(double)舍入值,格式化爲一個字符串之前:

多少位必須打印爲m或a的小數部分? 必須至少有一位數字來表示小數部分,並且 超出這個數字的位數必須與 唯一區分參數值與類型爲 double的相鄰值所需的位數一樣多。也就是說,假設x是精確的數學值 ,用該方法對 產生的十進制表示法表示一個有限的非零參數d。那麼d必須是x的最接近 的double值;或者如果兩個雙值同樣接近x,那麼d必須是其中一個 和d的有效數的至少顯著位必須 爲0

這樣做的結果是,String.valueOf(131.7d)將返回字符串「131.7」,即使參數的確切值是131.69999999999998863131622783839702606201171875。原因在於小數部分不能總是使用二進制分數來表示(與浮點數和雙精度一起使用)。

因此,新的new BigDecimal(String.valueOf(131.7))將創建一個精確值爲131.7的BigDecimal。 new BigDecimal(131.7)將創建一個精確值爲131.69999999999998863131622783839702606201171875的BigDecimal。

+0

這就解釋了這一點。謝謝! – Christian

6

如果你看一下API documentation

BigDecimal(double val) 
      Translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value. 

BigDecimal(String val) 
      Translates the string representation of a BigDecimal into a BigDecimal. 

這些其實都是不一樣的東西。在構造函數double中,它使用了浮點數(這本質上不準確)。在String構造函數中,它將採用您提供的確切值,並且而不是執行浮點轉換。因此,這實際上意味着上述構造函數不是「相同」表達式

+0

因此,在將值傳遞給BigDecimal之前,沒有其他方法可以獲得此計算的「正確」值(131.7 * 0.95 = 125.115),而不是將值轉換爲字符串?這對我來說似乎很奇怪! – Christian

+0

我不明白爲什麼2個具有相同輸入值的構造函數返回2個不同的結果。如果Double.valueOf(String.valueOf(131.7d))== 131.7d,爲什麼BigDecimal應該返回不同的值?這對我沒有任何意義! – Christian

+2

嗯,你實際上沒有在這裏回答基督徒的問題,因爲他在這兩種情況下都以131.7d和0.95d開頭。他觀察到的差異的原因並不是因爲BigDecimal構造函數的不同,而是String.valueOf(dobule)在轉換爲字符串之前間接舍入參數,而不是返回具有參數精確值的字符串。 – jarnbjo