java中多個數字運算后值不對(失真)處理方法


最近遇到一個bug ,在java里面計算兩個數字相減,633011.20-31296.30

得到的結果居然是601714.8999999999,丟失精度了,原來這是Java浮點運算的一個bug。

解決方法:網上找到了一些解決辦法,就是重新寫了一些浮點運算的函數。
下面就把這些方法摘錄下來,以供遇到同樣問題的朋友參考:

簡易計算器點擊下載

js中多個數字運算后值不對(失真)處理方法

調用方法:

 

public static void main(String[] args) throws Exception{
        System.out.println("加法未處理:0.05+0.01="+(0.05+0.01));
        System.out.println("加法已處理:0.05+0.01="+add(0.05,0.01));
        System.out.println("減法未處理:1.0-0.42="+(1.0-0.42));
        System.out.println("減法已處理:1.0-0.42="+sub(1.0,0.42));
        System.out.println("減法未處理:633011.20-31296.30="+(633011.20-31296.30));
        System.out.println("減法已處理:633011.20-31296.30="+sub(633011.20,31296.30));
        System.out.println("乘法未處理:4.015*10="+(4.015*100));
        System.out.println("乘法已處理:4.015*10="+mul(4.015,100));
        System.out.println("除法未處理:123.3/100="+(123.3/100));
        System.out.println("除法已處理:123.3/100="+division(123.3,100));
    }

控制台輸出效果:

 

加法未處理:0.05+0.01=0.060000000000000005
加法已處理:0.05+0.01=0.06
減法未處理:1.0-0.42=0.5800000000000001
減法已處理:1.0-0.42=0.58
減法未處理:633011.20-31296.30=601714.8999999999
減法已處理:633011.20-31296.30=601714.9
乘法未處理:4.015*10=401.49999999999994
乘法已處理:4.015*10=401.5
除法未處理:123.3/100=1.2329999999999999
除法已處理:123.3/100=1.23

 

 

 

 

java程序代碼

1.加法運算

 

    /**
     * 計算兩個值的加法運算
     * @param arg1
     * @param arg2
     * @return
     * @throws Exception
     */
    public static double add(double arg1,double arg2) throws Exception{
        String arg11 = arg1+"";
        String arg22 = arg2+"";
        int r1 = 0;
        int r2 = 0;
        int m = 0;
        try{
            r1=arg11.split("\\.")[1].length();
        }catch(Exception e){
            r1=0;
        }
        try{
            r2=arg22.split("\\.")[1].length();
        }catch(Exception e){
            r2=0;
        }
        m=(int) Math.pow(10,Math.max(r1,r2));
        
        return (arg1 * m + arg2 * m)/m;
    }

 

 

 

2.減法運算

 

    /**
     * 計算兩個值的減法運算
     * @param arg1
     * @param arg2
     * @return
     * @throws Exception
     */
    public static double sub(double arg1,double arg2) throws Exception{
        String arg11 = arg1+"";
        String arg22 = arg2+"";
        int r1 = 0;
        int r2 = 0;
        int m = 0;
        int n = 0;
        try{
            r1=arg11.split("\\.")[1].length();
        }catch(Exception e){
            r1=0;
        }
        try{
            r2=arg22.split("\\.")[1].length();
        }catch(Exception e){
            r2=0;
        }
        
        m = (int)Math.pow(10, Math.max(r1, r2));
        //last modify by deeka
        //動態控制精度長度
        n = (r1 >= r2) ? r1 : r2;
        double result = ((arg1 * m - arg2 * m) / m);
                
        //BigDecimal.ROUND_HALF_UP表示四舍五入,BigDecimal.ROUND_HALF_DOWN也是五舍六入,BigDecimal.ROUND_UP表示進位處理(就是直接加1),BigDecimal.ROUND_DOWN表示直接去掉尾數。
        BigDecimal b = new BigDecimal(result);
        result = b.setScale(n, BigDecimal.ROUND_HALF_UP).doubleValue();
        return result;
    }

 

 

 

3.乘法運算

 

    /**
     * 計算兩個值的乘法運算
     * @param arg1
     * @param arg2
     * @return
     * @throws Exception
     */
    public static double mul(double arg1,double arg2) throws Exception{
        String arg11 = arg1+"";
        String arg22 = arg2+"";
        int m = 0;
        try{
            m+=arg11.split("\\.")[1].length();
        }catch(Exception e){
            System.out.println("計算出錯");
        }
        try{
            m+=arg22.split("\\.")[1].length();
        }catch(Exception e){
            System.out.println("計算出錯");
        }
        return Integer.parseInt(arg11.replace(".",""))*Integer.parseInt(arg22.replace(".",""))/Math.pow(10,m);
    }

 

 

 

4.除法運算

 

    /**
     * 計算兩個值的除法運算
     * @param arg1
     * @param arg2
     * @return
     * @throws Exception
     */
    public static double division(double arg1,double arg2) throws Exception{
        String arg11 = arg1+"";
        String arg22 = arg2+"";
        int t1 = 0;
        int t2 = 0;
        int r1 = 0;
        int r2 = 0;
        try{
            t1=arg11.split("\\.")[1].length();
        }catch(Exception e){
            System.out.println("計算出錯");
        }
        try{
            t2=arg22.split("\\.")[1].length();
        }catch(Exception e){
            System.out.println("計算出錯");
        }
        r1=Integer.parseInt(arg11.replace(".",""));
        r2=Integer.parseInt(arg22.replace(".",""));
        double result = ((float)r1/r2)*(Math.pow(10,t2-t1));
        //BigDecimal.ROUND_HALF_UP表示四舍五入,BigDecimal.ROUND_HALF_DOWN也是五舍六入,BigDecimal.ROUND_UP表示進位處理(就是直接加1),BigDecimal.ROUND_DOWN表示直接去掉尾數。
        BigDecimal b = new BigDecimal(result);
        result = b.setScale(t1 + t2, BigDecimal.ROUND_HALF_UP).doubleValue();
        return result;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM