天天看點

double & operator[](int i)_java中double類型精度丢失問題及解決方法

點選上方“方志朋”,選擇“設為星标”

回複”666“擷取新整理的面試文章

double & operator[](int i)_java中double類型精度丢失問題及解決方法

來源:

https://blog.csdn.net/yacolspace/article/details/78287394

今天在項目中用到double類型資料加減運算時,遇到了一個奇怪的問題,比如1+20.2+300.03,理論上結果應該是321.23,其實結果并不是這樣。

public double add() {
        double number1 = 1;
        double number2 = 20.2;
        double number3 = 300.03;
        double result = number1 + number2 + number3;
        System.out.println(result);
        return result;
    }
           

列印結果如下:

double & operator[](int i)_java中double類型精度丢失問題及解決方法

這是為什麼呢?又該如何解決呢?

在使用Java中double 進行運算時,經常出現精度丢失的問題,總是在一個正确的結果左右偏0.0000**1。float和double隻能用來做科學計算或者是工程計算,在商業計算中我們要用 java.math.BigDecimal。BigDecimal一共有4個夠造方法,我們隻考慮兩個進行比較,分别是

BigDecimal(double val)
          Translates a double into a BigDecimal.
BigDecimal(String val)
          Translates the String repre sentation of a BigDecimal into a BigDecimal.
           

上面的API簡要描述相當的明确,而且通常情況下,上面的那一個使用起來要友善一些。我們可能想都不想就用上了,會有什麼問題呢?

現貼出BigDecimal的一個構造函數的文檔供大家參考

double & operator[](int i)_java中double類型精度丢失問題及解決方法

解決方法

相信從上面的文檔大家也已經找出了解決方法,在需要精确的表示兩位小數時我們需要把他們轉換為BigDecimal對象,然後再進行運算。

另外需要注意,使用BigDecimal(double val)構造函數時仍會存在精度丢失問題,建議使用BigDecimal(String val)。這就需要先把double轉換為字元串然後在作為BigDecimal(String val)構造函數的參數。轉換為BigDecimal對象之後再進行加減乘除操作,這樣精度就不會出現問題了。這也是為什麼有關金錢資料存儲都使用BigDecimal。

處理double類型資料的加、減、乘、除運算時,使用如下方法:

/**
     * 加法運算
     * @param m1
     * @param m2
     * @return
     */
    public static double addDouble(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.add(p2).doubleValue();
    }

    /**
     * 減法運算
     * @param m1
     * @param m2
     * @return
     */
    public static double subDouble(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.subtract(p2).doubleValue();
    }

    /**
     * 乘法運算
     * @param m1
     * @param m2
     * @return
     */
    public static double mul(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.multiply(p2).doubleValue();
    }


    /**
     * 除法運算
     * @param   m1
     * @param   m2
     * @param   scale
     * @return
     */
    public static double div(double m1, double m2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("Parameter error");
        }
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.divide(p2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
           

驗證文章開頭提到的問題是否解決,

public double addDouble() {
        double result1 = add(1, 20.2);
        double result2 = add(result1, 300.03);
        System.out.println("使用BigDecimal時結果值:" + result2);
        return result2;
    }
           

列印結果值

double &amp; operator[](int i)_java中double類型精度丢失問題及解決方法

跟預想中的結果值一樣,解決了double類型資料加減操作時精度丢失的問題。

熱門内容:

一次SQL查詢優化原理分析

start.aliyun.com正式上線

驚呆了,Spring Boot居然這麼耗記憶體!

兩小時入門Docker

一個基于SpringBoot的項目骨架

Spring Boot注解大全,一鍵收藏了!

面試:高頻面試題:如何保證緩存與資料庫的雙寫一緻性?

SpringBoot記憶體洩露,排查竟這麼難!

double &amp; operator[](int i)_java中double類型精度丢失問題及解決方法

最近面試BAT,整理一份面試資料《Java面試BAT通關手冊》,覆寫了Java核心技術、JVM、Java并發、SSM、微服務、資料庫、資料結構等等。

擷取方式:點“在看”,關注公衆号并回複 666 領取,更多内容陸續奉上。

明天見(。・ω・

繼續閱讀