金額的存儲

存在的問題

public class Client{
 public static void main(String[] args){
   System.out.print(10.00-9.60);
     }
}

我們期望的結果爲0.4,但是打印的結果卻是0.40000000000000036

原因:機器運算時二進制運算,將0.4轉爲二進制,他是無限循環小數,可以這樣理解在十進制世界裏沒有辦法準確表示1/3,這樣一來結果很容易出現偏差
嘗試解決方案:

publi class client{
 public static void main(String[] args){
  NumberFormat f=new DecimalFormat("#.##");
  Syso(f.format(10.00-9.60));
  }
}

結果:0.4
看似解決了,但是隱藏了一個很深的問題,一般金融會計系統會記錄小數點後四位,
但是在彙總,展現,報表中則只記錄小數點的2位小數,如果使用浮點數來計算貨幣,
在大批量的加減乘除後結果會有很大的差距!會計系統要的就是準確,但是卻因爲計算機的緣故不準確了
真正解決方案:
1 使用BigDecimal
專門用來彌補浮點數無法精確計算的缺憾而設計的類,並且本身也提供了加減乘除的常用數據算法.
特別是與數據庫Decimal類型的字段映射時,BigDecimal時最優的結解決方案
金額的運算(小數的精確計算)

BigDecimal b1 = new BigDecimal("0.03");
        BigDecimal b2 = new BigDecimal("0.04");
        // 加法
        System.out.println(b1.add(b2));
        // 減法
        System.out.println(b2.subtract(b1));
        // 乘法
        System.out.println(b2.multiply(b1));
        // 除法
        // 如果 BigDecimal 是正的,則做 ROUND_UP 操作;如果爲負,則做 ROUND_DOWN 操作。    
     System.out.println(b2.divide(b1, RoundingMode.HALF_UP));
 注:在這裏HALF_UP是一種舍入模式
  BigDecimal和RoundingMode是一個絕配,想要採用什麼舍入模式
  使用RoundingModel設置即可,目前java支持七種舍入方式:
   1 ROUND_UP:遠離零方向舍入
     也就是說,想絕對值最大限額方向舍入,只要捨棄位非0即進位
   2 ROUND_DOWN:遠離零方向舍入
     也就是說,想絕對值最小的方向輸入,注意:所有的位都捨棄,不存在進位情況
   3 ROUND_CEILING:向正無窮方向舍入
     如果是正數,舍入行爲類似ROUND_UP;
     如果是負數,舍入行爲類似於ROUND_DOWN;
     注意:Math.round方法使用的即爲此模式
   4 ROUND_FLOOR:向負無窮方向舍入.
     如果是正數,則舍入行爲類似於ROUND_DOWN;
     如果爲負數,則舍入行爲 類似於ROUND_UP;
   5 HALF_UP:最近數字舍入(5進)  最經典的四捨五入
   6 HALF_EVEN:銀行家算法
     規定:
     四捨六入五考慮,五後非零就進一,五後爲0看奇偶,五前爲偶應捨去,

五前爲奇要進一
2 使用整型
把參數與運算的值擴大100倍,並轉爲整形,然後在展現時,再縮小100倍,
這樣處理的好處是計算簡單,準確,但只適用於一般在非金融行業應用較多如POS機

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章