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;
    }
原文地址:https://www.cnblogs.com/shuilangyizu/p/10044037.html