看圖
如圖
讀過effective java的都知道,其中第49條就是:如果需要精確的答案,請避免使用float和double
所以在涉及到貨幣計算的時候一般使用BigDecimal
分析
但是BigDecimal也要講究使用方法,否則也可能事與願違,沒有獲得你想要的效果。
BigDecimal.valueof(0.99),可以看一下此方法的具體實現:
可以看到此方法先將參數轉成了string類型,然後在執行參數爲String類型的BigDecimal的構造函數。這樣的結果一般就是我們想要的。
所以在使用BigDecimal的時候,要麼使用newBigDecimal(String value),要麼使用BigDecimal.valueof(doublevalue)。
那如果參數爲float類型的,比如BigDecimal.valueOf(0.99f)的值是多少呢?
首先此函數會自動進行精度擴展,將float類型的0.99轉成double類型的,因爲0.99本身就是無法用二進制表示的,也就說無論你的精度是多少位,都無法用二進制來精確表示0.99,或者你用二乘來判斷(0.992=1.98 0.982=1.960.96*2=1.92 。。。永遠無法得到一個整數)。這就是二進制計算機的缺點,就如同十進制也也無法表示1/3,1/6一樣。
所以在0.99f轉成double時,進行了精度擴展,變成了0.9900000095367432,而接着轉成字符串,最後轉成BigDecimal.
輸出結果如下:
至於爲什麼是這個數,那就涉及到二進制的補碼移碼的問題,double類型的0.99在計算機中的存儲形式。這裏你只要記得它絕不是你想要的精確的0.99即可。也爲精確計算埋下了隱患。
jdk中已經明確不建議使用new BigDecimal(double value)這種形式的構造函數,這是爲什麼呢???
仍然是因爲double類型不夠精確,
輸出結果:
總結:
總之,在涉及到精確計算的時候,使用浮點型的數據很可能會出現你意想不到的結果。即使在使用BigDecimal的時候,也應該使用new BigDecimal(Stringvalue) 或 BigDecimal.valueof( double value)
————————————————
版權聲明:本文爲CSDN博主「菜鳥很菜」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/j754379117/article/details/52238396