最近遇到一個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; }