java中多个数字运算后值不对(失真)处理方法
最近遇到一个bug ,在java里面计算两个数字相减,633011.20-31296.30
得到的结果居然是601714.8999999999,丢失精度了,原来这是Java浮点运算的一个bug。
解决方法:网上找到了一些解决办法,就是重新写了一些浮点运算的函数。
下面就把这些方法摘录下来,以供遇到同样问题的朋友参考:
调用方法:
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; }