[英]What's the right way to parseFloat in Java
我注意到Java浮點精度的一些問題
Float.parseFloat("0.0065") - 0.001 // 0.0055000000134110451
new Float("0.027") - 0.001 // 0.02600000000700354575
Float.valueOf("0.074") - 0.001 // 0.07399999999999999999
我不僅有Float
的問題,還有Double
。
有人可以解釋幕后發生的事情,我們怎樣才能獲得准確的數字? 在處理這些問題時,處理此問題的正確方法是什么?
問題在於float
具有有限的精度; 它不能完全代表0.0065
。 (當然, double
也是如此:它具有更高的精度,但仍然是有限的。)
使上述問題更加明顯的另一個問題是0.001
是一個double
而不是float
,所以你的float
被提升為double
來執行減法,當然在這一點上系統無法恢復double
可能代表的缺失精度。 為了解決這個問題,你會寫:
float f = Float.parseFloat("0.0065") - 0.001f;
使用0.001f
而不是0.001
。
看看每個計算機科學家應該知道的關於浮點運算的內容 。 你的結果對我來說是正確的。
如果您不喜歡浮點數的工作方式,請嘗試使用類似BigDecimal的方法 。
你得到了正確的結果。 沒有像0.027那樣的float
,也沒有這樣的double
。 如果使用float
或double
則總會出現這些錯誤。
float
和double
存儲為二進制分數 :類似於1/2 + 1/4 + 1/16 ......您無法將所有十進制值精確地存儲為有限精度二進制分數。 這在數學上是不可能的。
唯一的選擇是使用BigDecimal
,您可以使用它來獲取精確的十進制值。
如果浮點字面值以字母
F
或f
結尾,則浮點字面值為float類型; 否則它的類型是雙倍的,它可以選擇以字母D
或d
結尾。
所以我認為你的文字( 0.001
)是雙打的,你從浮動中減去雙打。
試試這個:
System.out.println((0.0065F - 0.001D)); // 0.005500000134110451
System.out.println((0.0065F - 0.001F)); // 0.0055
......你會得到:
0.005500000134110451
0.0055
因此,在文字中添加F
后綴,您應該得到更好的結果:
Float.parseFloat("0.0065") - 0.001F
new Float("0.027") - 0.001F
Float.valueOf("0.074") - 0.001F
我會將你的浮點數轉換為字符串,然后使用BigDecimal。
這個鏈接解釋得很好
new BigDecimal(String.valueOf(yourDoubleValue));
不要使用BigDecimal雙構造函數,因為你仍然會得到錯誤
如果您需要任意精度,請使用BigDecimal,不要浮動或加倍。 你會看到使用float這種性質的各種舍入問題。
另外要小心不要使用BigDecimal的float / double構造函數,因為它會有同樣的問題。 請改用String構造函數。
浮點不能准確表示十進制數。 如果您需要在Java中准確表示數字,則應使用java.math.BigDecimal類:
BigDecimal d = new BigDecimal("0.0065");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.