java中double型數字運算異常的解決方法

· 會遇到的異常問題

    System.out.println(12.0-8.53);
    System.out.println(26.99+20);
    System.out.println(0.033*100);
    System.out.println(16.33/100);

    /*output:
    3.4700000000000006
    46.989999999999995
    3.3000000000000003
    0.16329999999999997
    */

· 原因

之所以會出現這樣的運算異常是因爲Java中的簡單浮點數類型float和double不能夠直接進行運算。因爲雖然大多數情況下是正常的,但是偶爾會出現如上所示的問題。這個問題其實不是Java的bug,而是由於計算機本身是二進制完成的,而浮點數實際上只是個近似值,所以從二進制與十進制浮點數的轉化容易發生精度容易丟失,導致精度下降。

· 解決方法

Java.math包中提供的BigDecimal類可以解決這個問題。但是不能直接將double型數直接包裝在BigDecimal對象當中,而是要求必須先將double數字通過它的包裝類(Double)重載的toString(double d)轉化爲String類型之後的結果才能傳入BigDecimal構造器,進而創建對象調用方法進行運算,最終的輸出結果再以double類型返回

  • 加法
    public static double add(double a,double b){
        BigDecimal d1 = new BigDecimal(Double.toString(a));
        BigDecimal d2 = new BigDecimal(Double.toString(b));
        return d1.add(d2).doubleValue();    
    }
  • 減法
    public  static double sub(double a,double b){
        BigDecimal d1 = new BigDecimal(Double.toString(a));
        BigDecimal d2 = new BigDecimal(Double.toString(b));
        return d1.subtract(d2).doubleValue();
    }
  • 乘法
    public  static double mul(double a,double b){
        BigDecimal d1 = new BigDecimal(Double.toString(a));
        BigDecimal d2 = new BigDecimal(Double.toString(b));
        return d1.multiply(d2).doubleValue();
    }
  • 除法

除法我們會用到 public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode),這裏有必要將這當中的兩個參數scale和roundingMode簡單介紹一下:
1. scale是用來指定最終結果的精度,由用戶自定義;
2. roundingMode是指明舍入方式的,用戶不能自定義,而是用BigDecimal類當中已經提供的變量。常用的roundingMode一般主要有兩個:ROUND_HALF_UP,它表示指定精度的後一位數字如果 >=5 則向上進一位,否則捨去。例如,3.0555,如果指定精度爲3,結果應當精確到千分位,而此時在千分位後面的數字等於5,因此向上進一位,最終結果爲3.056;ROUND_HALF_DOWN,它表示指定精度的後一位數字如果 >5 則向上進一位,否則捨去。例如,7.06475,如果指定精度爲4,結果應當精確到萬分位,而此時在萬分位後面的數字等於5,因此向直接捨去,最終結果爲7.0647.

    //這裏的roundingMode可直接用類BigDecimal調用靜態變量ROUND_HALF_UP或ROUND_HALF_DOWN賦值
    public static double div(double a,double b,int scale,int roundingMode){
        BigDecimal d1 = new BigDecimal(Double.toString(a));
        BigDecimal d2 = new BigDecimal(Double.toString(b));
        return d1.divide(d2,scale , roundingMode).doubleValue();
    }
發佈了32 篇原創文章 · 獲贊 51 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章