2013-10-26 20 views
0

所以我的BigDecimal持有價值0.99和我調用:Java:爲什麼相同浮點值的十六進制值不同?

  • Float.toHexString(rationalNumber.floatValue())我得到0x1.fae148p-1
  • Double.toHexString(rationalNumber.doubleValue() )我得到0x1.fae147ae147aep-1

我想因爲我們是代表像0.99少數,我們應該得到相同的十六進制值,而不管。同意?

碼(失敗測試):

@Test public void testDelta() { 
    BigDecimal rationalNumber = new BigDecimal("0.99").setScale(2,BigDecimal.ROUND_DOWN); 

    String hexFromFloat = Float.toHexString(rationalNumber.floatValue()); 
    String hexFromDouble = Double.toHexString(rationalNumber.doubleValue()); 

    String hexFromFloatMsg = rationalNumber.floatValue() + " = " + hexFromFloat; 
    String hexFromDoubleMsg = rationalNumber.doubleValue() + " = " + hexFromDouble; 

    Assert.assertEquals(hexFromFloatMsg + ", " + hexFromDoubleMsg, hexFromDouble, hexFromFloat); 
} 

輸出:

org.junit.ComparisonFailure: 0.99 = 0x1.fae148p-1, 0.99 = 0x1.fae147ae147aep-1 
Expected :0x1.fae147ae147aep-1 
Actual :0x1.fae148p-1 

回答

2

的差別發生在這兩個操作:

rationalNumber.floatValue() 
rationalNumber.doubleValue() 

每個這些轉換一個BigDecimal值的0.99至浮點。在十六進制浮點數(二進制冪的小​​數指數)中,.99是0x1.fae147ae147ae147 ... p-1。當它轉換爲float時,只能存儲24位有效數(小數部分),因爲這是float類型對有效數的所有位。 (顯式存儲23位;其他部分是隱含的)。因此,轉換必須將.99的精確值舍入爲適合24位的值。這產生了1.fae148p-1。如果你在二進制文件中寫入1.fae147ae147ae147 ...並計算出24位,你可以看到舍入發生在哪裏。在這裏它們的前24位用粗體顯示:1.11111010111000010100011 110101110000101000111 ... p-1。四捨五入時,我們看看被刪除的位,看到它們超過最低位的一半(第一位被移除爲1,並且還有另外一位),並決定四捨五入。所以舍入產生1.11111010111000010100100p-1。在十六進制中,即1.fae148p-1。

當.99轉換爲double時,可存儲53位有效位。所以它是在不同的位置四捨五入。這會產生0x1.fae147ae147aep-1。

這兩個值不同,直接比較它們會報告它們不同,並將它們從浮點格式轉換爲十六進制數字會產生不同的結果。

+0

非常感謝埃裏克,你可以請讀這個問題[http://stackoverflow.com/questions/19590878/java-double-in-place-of-float],看看我的編輯,請讓我知道,如果你同意發現。非常感謝。 – jakstack

-1

,因爲我們是代表像0.99少數,我們應該得到相同的十六進制值,而不管。同意?

這是一個十進制小精度,但是,正如你所看到的,它的十六進制表示重複(0x1.f(ae147)*)。它正好被代表,但它不能完全是印刷

+0

謝謝,請你澄清一下:「這是一個十進制的小精度。」爲什麼不能完全打印?也看不出它是如何重複的,我可以看到高達0x1.fae14是相同的,但其餘的是不同的。 「 – jakstack

+0

」這是一個十進制的小精度「意味着base-10中的表示只需要兩位精度的數字,可以精確打印。我所說的重複是在十六進制表示中,'ae147'部分重複。數字確實是0x1。fae147ae147ae147ae147ae147ae147ae147ae147ae147ae147ae147ae147ae147 ...'。它只是打印到幾位數字。 – Kevin