2012-05-15 56 views
1

可能重複:
Moving decimal places over in a double奇怪樓舍

我有在Java中這個奇怪的問題,我有以下代碼:

double velocity = -0.07; 
System.out.println("raw value " + velocity*200); 
System.out.println("floored value " + Math.floor(velocity*200)); 

我有以下的輸出:

raw value -14.000000000000002 
floored value -15.0 

那些trader 0002搞砸了一切,順便說一句,不應該是那個traling 2,我認爲它應該在小數點後都是零,我可以擺脫那2嗎?

更新:感謝您的幫助,你們知道有什麼方法可以在不調用doubleValue方法的情況下對BigDecimal對象進行四捨五入嗎?

+0

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – NPE

回答

2

使用BigDecimal ...上面的問題是在具有有限內存的計算機上使用的表示方案的一個衆所周知的舍入問題。問題是答案在二進制(即基數2)系統中是重複的(即像1/3 = 0.33333333 ...帶有十進制)並且無法正確顯示。一個很好的例子是1/10 = 0.1,它是二進制的0.000110011001100110011001100110011 ...。在某點之後,1和0必須結束,導致感知錯誤。

希望你不是在生活中至關重要的東西......例如http://www.ima.umn.edu/~arnold/disasters/patriot.html。由於舍入誤差,28人喪生。

+2

我沒有downvote,但你可能想要解決你的措辭:「非理性」和「不完全可代表」。 – Mysticial

+2

這個問題與Java完全沒有關係 –

+1

不,這個數字不是非理性的,它是一個簡單的理性值:-)四捨五入的問題通常是浮點運算,不是Java特有的。 –

1

Java雙打遵循IEEE 754浮點算法,它不能以無限精度表示每個實數。這次收集是正常的。在內部表示中你不能擺脫它。您當然可以使用String.format打印結果。

3

The Floating-Point Guide

爲什麼我的數字,像0.1 + 0.2加起來一個漂亮的圓0.3,而是我得到一個怪異的結果像0.30000000000000004?

由於內部計算機使用格式(二進制浮點數) ,因此無法準確表示數字,如0.1,0.2或0.3。

當代碼被編譯或解釋時,您的「0.1」已經被 舍入到該格式的最接近的數字,即使在計算髮生之前,這也會導致一個小的舍入誤差。

如果您需要的數字恰好等於特定的期望值,則不能使用double。有關詳細信息,請閱讀鏈接到的網站。

4

因爲floor(-14.000000000000002)確實是-15

您會看到,floor被定義爲小於或等於參數的最大整數。由於-14.000000000000002不是整數,最接近的整數-15

那麼,現在讓我們來明白爲什麼-0.07 * 200不完全是-14。這是因爲浮點數的內部表示是基於2,所以分母不是2的冪的分數不能用100%的精度表示。 (與無法用小數點位數表示1/3的小數部分相同)。因此,velocity的值不完全是-0.07。 (當編譯器看到常量-0.07時,它會用一個非常接近-0.07的二進制分數靜默替換它,但實際上並不等於。)這就是爲什麼velocity * 200不完全是-14