關於float和double計算精度缺失解決方法筆記
阿新 • • 發佈:2018-12-05
最近在專案中的財務管理模組遇到一個問題就是資料庫欄位建的型別是float,在計算後會引起精度缺失問題
拋開資料庫建立的不當以外,遇到這個問題的解決方法如下:
例子:
public static void main(String[] args) { // TODO Auto-generated method stub Float f1 = 24f; Float f2 = 40.3f; Double d1 = 24d; Double d2 = 40.3; System.out.println(f1*f2); System.out.println(d1*d2); }
輸出結果為
967.19995
967.1999999999999
解決方法:
BigDecimal
我們將float或者double型別的先轉換成bigdecimal型別再進行計算,就非常精確,所以這就是為什麼金額(金錢)相關的資料儲存型別都用decimal或者bigdecimal。
看了一下bigdecimal的構造方法很多
這塊建議使用BigDecimal(String val)來解決
原因在此引用一位前輩的一段話
有人可能認為在 Java 中寫入 new BigDecimal(0.1) 所建立的 BigDecimal 正好等於 0.1(非標度值 1,其標度為 1),但是它實際上等於 0.1000000000000000055511151231257827021181583404541015625。這是因為 0.1 無法準確地表示為 double(或者說對於該情況,不能表示為任何有限長度的二進位制小數)。這樣,傳入 到構造方法的值不會正好等於 0.1(雖然表面上等於該值)。
所以,使用double和float作為資料來源的話,使用public BigDecimal(double val)產生的結果帶有一定的不可預知性。
最後貼上一些bigdecimal的簡單使用方法
public static void main(String[] args) { // TODO Auto-generated method stub //bigdecimal比較大小 BigDecimal big1 = new BigDecimal("21.6"); BigDecimal big2 = new BigDecimal("10.8"); System.out.println(big1.compareTo(big2)); //-1表示小於,0是等於,1是大於 if(big2.compareTo(big1)>0){ //如果big2>big1 System.out.println("--------"+big2); }else{ //否則 System.out.println("--------"+big1); } //bigdecimal計算 //加 System.out.println(big1.add(big2)); //減 System.out.println(big1.subtract(big2)); //乘 System.out.println(big1.multiply(big2)); //除 System.out.println(big1.divide(big2)); }
輸出結果:
1
--------21.6
32.4
10.8
233.28
2