2012-08-06 194 views
4

爲什麼下面的代碼:意外的結果

System.out.println((int)(19.99 * 100));

產生結果 「1998年」?

回答

9

舍入誤差。如果你看一下你的計算不投的結果,您可以:

1998.9999999999998 

所以,當你投爲int,小數部分被丟棄,而不是圍捕,你會得到1998

的道德是,如果你需要一個確切的答案,根本不使用float/double。如果你談論的是像金錢這樣的離散值,那麼使用int並處理原子單位(例如便士)。如果你確實需要精確的小數,那麼BigDecimal是你的朋友。

雖然您可以使用Math.round()將結果帶到預期的位置,但這並不適用於所有情況,也無法解決潛在的問題。

+1

我不認爲這解決了真正的問題,這是無法準確地表示19.99 – 2012-08-06 11:54:42

+0

@BrianAgnew我已經添加了一點現在來解決這個問題。 – berry120 2012-08-06 11:56:43

5

這是因爲19.99不能完全表示。

System.out.println(new BigDecimal(19.99)); 

打印出這個實際代表的值,它最接近它可以表示的19.99。

19.989999999999998436805981327779591083526611328125 

19.99 * 100

System.out.println(new BigDecimal(19.99 * 100)); 

這是

1998.999999999999772626324556767940521240234375 

的問題是,你有一個代表性的錯誤在19.99這是仍然存在的時候乘以100,你會得到一個號碼這太小了。

如果您通過100和回合下來這就是(int)不應該期望獲得1998年

另一種方法是

System.out.println(Math.round(19.99 * 100)); 
+5

雖然這是真的,但這個原因並不能解釋1998年的迴歸,19.99 * 100是1999. – 2012-08-06 11:51:40

+0

我認爲這個回答解決了這個問題的*基礎*。 +1 – 2012-08-06 11:53:52

+0

@SeanKenny我不關注。 '1998.9999999999998436805981327779591083526611328125'向下取整是'1998'? – 2012-08-06 11:54:48

1

因爲19.99 * 100的計算將產生多1998.999999,你將它轉換爲int將丟棄它的小數部分。

1

這是由於四捨五入的問題。 doublefloat很容易出現這些問題,這就是爲什麼建議您使用BigDecimal類。

此代碼應打印的期望是什麼:

BigDecimal bg = new BigDecimal("19.99"); 
System.out.println(bg.multiply(new BigDecimal("10"))); 

這產生了:

199.90

1
System.out.println((19.99 * 100)); 

產生的結果爲1998年。9999999999998加入int鑄造它截斷小數部分並返回1998

1

浮點數據類型(float和double在Java中)只能近似表示大多數小數值。有關更多詳情,請參閱Joshua Bloch's關於此主題的智慧詞彙。