2011-08-16 31 views
3

我對將此字符串解析爲Double時遇到的這種特殊「錯誤」感到非常困惑。NumberFormat解析問題

我已經設置了NumberFormat屬性和符號。

當通過與15個數字和2位小數(例如:str = "333333333333333,33") 一個字符串,並用Number num = NumberFormat.parse(str)解析它的結果是省略了數字。

num的實際值是3.333333333333333E14

這似乎與字符串合作與全1,2的和4的,但...

任何人都可以告訴我嗎?

乾杯 恩里科

回答

5

DecimalFormat.parse方法,將在這種情況下返回一個Double,其具有有限精度

你不能指望它總是能夠返回一個完全代表輸入的數字。

您可以使用BigDecimal.setParseBigDecimal來允許數字格式從解析方法中返回BigDecimal。這Number能夠以任意精度表示您的值。 (謝謝@Peter Lawrey指出這一點!)

+0

有沒有一種解決方法,使它不解析,而是讓它變長? – Mallinok

+0

'long'是一個整數類型,因此你會失去小數部分(',33')。 – aioobe

+0

@aioobe,你可以看看Java 1.4的文檔嗎?這個方法是在Java 5.0中添加的。 http://download.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html#setParseBigDecimal%28boolean%29 –

6

簡短的回答;由於圓誤差

(double) 111111111111111.11 != (double) 111111111111111.1 

(double) 333333333333333.33 == (double) 333333333333333.3 

如果你想更精確,使用setParseBigDecimal和解析會返回一個BigDecimal。


爲什麼會發生這種情況?這是因爲你處於double精度的極限。這17個很好,因爲它可以代表。 2的數量只是雙倍,而雙店的兩個功率是17箇中的兩個,所以17個和17個八個都是好的。

但是,17三位需要比double多一位來表示該值,並且該最後一位被截斷。同樣,17五,六和九也有舍入誤差。

double[] ds = { 
     111111111111111.11, 
     222222222222222.22, 
     333333333333333.33, 
     444444444444444.44, 
     555555555555555.55, 
     666666666666666.66, 
     777777777777777.77, 
     888888888888888.88, 
     999999999999999.99}; 
for (double d : ds) { 
    System.out.println(d + " - " + new BigDecimal(d)); 
} 

打印以下內容。在打印之前,double稍微圓整,BigDecimal顯示雙精度值的確切值。

1.1111111111111111E14 - 111111111111111.109375 
2.2222222222222222E14 - 222222222222222.21875 
3.333333333333333E14 - 333333333333333.3125 
4.4444444444444444E14 - 444444444444444.4375 
5.5555555555555556E14 - 555555555555555.5625 
6.666666666666666E14 - 666666666666666.625 
7.777777777777778E14 - 777777777777777.75 
8.888888888888889E14 - 888888888888888.875 
1.0E15 - 1000000000000000 
+1

+1,awsome答案。 – aioobe

+0

@aioobe,來自你,這意味着什麼。 ;) –

+0

heh thanks :-)我對你的第二個表達式感到驚訝,所以我寫了一個[後續問題](http://stackoverflow.com/questions/7076653/why-is-arbitrary-precision-in-double-literals -allowed-in-java) – aioobe