2016-01-20 122 views
0

我剛剛經歷過的錯誤,其中兩個號碼都被比較,我發現以下有趣:double和float值比較

assert 1 == 1;//true   
    assert 1d == 1;//true   
    assert 1 == 1f;//true   
    assert 1d == 1f;//true 
    assert 1.1 == 1.1;//true   
    assert 1.1d == 1.1;//true   
    assert 1.1 == 1.1f;//false   
    assert 1.1d == 1.1f;//false 

我的問題是:爲什麼只有最後兩個語句是假的?

+0

很好的解釋:https://randomascii.wordpress.com/2012/06/26/doubles-are-not-floats-所以不要比較他們/ –

+1

你必須閱讀[每個計算機科學家應該知道什麼關於浮點運算](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) 。這是這個規範的資源。 –

+0

檢查兩種不同類型值的平等點有什麼意義......沒關係。 – haifzhan

回答

13

這是因爲四捨五入。

1可以完全表示爲double或float,因此前4個比較按預期工作。

1.1 == 1.1比較雙重自身並按預期工作。

1.1d == 1.1與上述完全相同(d暗示在1.1中)。

最後兩個比較比較1.1雙精度到1.1浮點數。除1.1不能完全表示爲float(或double),所以它會四捨五入到最接近的float(或double) - 但double有一個「higher resolution」,所以它們不會被類似地舍入。

,看看具體的值:

System.out.println(new BigDecimal(1.1f)); //1.10000002384185791015625 
System.out.println(new BigDecimal(1.1d)); //1.100000000000000088817841970012523233890533447265625 

正如意見建議的@yshavit,當你比較雙到浮,浮被轉換爲雙(due to numeric promotion),所以你真的比較兩個雙打:

System.out.println(new BigDecimal((double) 1.1f)); //1.10000002384185791015625 
System.out.println(new BigDecimal(1.1d)); //1.100000000000000088817841970012523233890533447265625 
+1

我想爲獎勵積分,'System.out.println(新的BigDecimal((雙)1.1f))',以顯示如何將四捨五入的浮點數擴大到一倍。 – yshavit

1

數字1.1不能完全用二進制浮點表示,因此在4字節浮動和8字節略有不同雙重代表。

因此,最後兩個是錯誤的,因爲它們將一個double與一個浮點數比較,這個數字不能完全代表表示。
另一隻比較雙具有雙或使用可以精確表示像1.0

+0

然後解釋「assert 1d == 1f; // true」 – logger

+0

閱讀我更新的答案1.1 cannor可以表示 – AlexWien

2

啓動此程序的值

public static void main(String... args) { 
    System.out.println("1.1f bits: " + Long.toBinaryString(Double.doubleToLongBits(1.1f))); 
    System.out.println("1.1d bits: " + Long.toBinaryString(Double.doubleToLongBits(1.1d))); 
} 

它yelds

1.1f as double: 11111111110001100110011001100110100000000000000000000000000000 
1.1d as double: 11111111110001100110011001100110011001100110011001100110011010 

這樣做的原因行爲是字面1.1,即小數部分1.1 dec不具有作爲二進制小數的有限表示,並且IEEE-754存儲器es數字作爲二進制分數。所以它是四捨五入的,結果取決於轉換時可用的位數(順便說一句,轉換甚至不會在運行時發生 - 這是編譯器的工作)。

當比較不同規模的運營商時,推薦較小的運營商。請注意,這並不是說double和float不能相等的情況下:

3.1f != 3.1d 
3.0f == 3.0d