1. 程式人生 > >double 轉 BigDecimal 精度問題

double 轉 BigDecimal 精度問題

請看圖:

    //double 轉 BigDecimal 精度測試
    @Test
    public void a (){
        Double Dou = 5.56;
        BigDecimal bigDou1 = new BigDecimal(Dou);
        BigDecimal bigDou2 = BigDecimal.valueOf(Dou);
        log.info("Double轉BigDecimal,使用構造方法轉化="+bigDou1);//5.55999999999999960920149533194489777088165283203125
        log.info("Double轉BigDecimal,使用字串形式轉化="+bigDou2);//5.56
    }

很明顯,經過 double 轉 BigDecimal 後,我們最初的值已經發生變化,所以通常我們在做型別轉換的時候推薦使用 BigDecimal.valueOf(...);

分析:JDK1.8 原始碼

BigDecimal bigDou1 = new BigDecimal(Dou);

這個轉換結果是double的二進位制浮點值的精確十進位制表示,其值得結果不是我們可以預測的,如上測試類,經過型別轉換:5.56變成了5.55999999999999960920149533194489777088165283203125。是因為轉化過程預設使用了精度和舍入模式:

public BigDecimal(double val, MathContext mc) {}; 舍入模式為:public final static int ROUND_HALF_UP =4;也是一種四捨五入,官方解釋:該四捨五入模式向“最近鄰居”轉彎,除非兩個鄰居都是等距的,在這種情況下是圓括弧的。

BigDecimal bigDou2 = BigDecimal.valueOf(Dou);

原始碼:  

  public static BigDecimal valueOf(double val) {
        return new BigDecimal(Double.toString(val));
    } 

使用double通過所提供的規範的字串表示Double.toString(double)方法。呼叫BigDecimal bigDou2 = BigDecimal.valueOf("String");此時5.56=5.56.所以進行型別轉換推薦此方法。

 另外:如果資料庫儲存,可以直接寫入 double。

INSERT INTO statistic_info (`id`,`amount`)  VALUES (#{bean.id},#{bean.amountDouble});