最近在改同事bug的时候,发现了一个关于使用BigDecima来做除法时遇到的问题。就是多次调用除法方法,并且含有小数的时候 丢失了精度。计算的题目是:500/4.9/5 最后得到的结果是20 但是使用计算器得到的真正的结果
后面通过分析,发现了除法可以传入1,2,3个参数 而我同事在这里使用的传入2个参数的方法,所以后面我分析问题的时候,就把这3个参数都使用了一次 代码如下:
public class Test {
public static void main(String[] args){
BigDecimal val=new BigDecimal("500");
BigDecimal val1=new BigDecimal("4.9");
BigDecimal val2=new BigDecimal("5");
/**
* 使用BigDecimal的除法对象来计算500/4.9/5的结果
*/
String result2=val.divide(val1,4).divide(val2,4).toString();
System.out.println("两个参数:"+result2);
String result3=val.divide(val1,4,BigDecimal.ROUND_HALF_UP).divide(val2,4,BigDecimal.ROUND_HALF_UP).toString();
System.out.println("三个参数:"+result3);
String result1=val.divide(val1).divide(val2).toString();
System.out.println("单个参数:"+result1);
}
}
得到的结果打印如下:
有的朋友也许会疑惑 为什么我的构造参数里面使用的是字符串,而不是直接传数字类型。关于这个问题,可以参考看下我的这篇文章https://blog.csdn.net/u014508939/article/details/94156127
再回到这个问题里,我们可以看到,传入2个参数,第一个参数为除数,第二个为精度到哪位,而打印出来的结果就是问题的所在,精度都丢失了。
而传入3个参数,在前2个的基础上,第三个参数增加了Decimal.ROUND_HALF_UP 最后计算出来的结果就是正确的
最后当我传入1个除数为参数的时候,直接崩溃发生了异常,提示Non-terminating decimal expansion; no exact representable decimal result. 通过百度得知:原来JAVA中如果用BigDecimal做除法的时候一定要在divide方法中传递第二个参数,定义精确到小数点后几位,否则在不整除的情况下,结果是无限循环小数时,就会抛出以上异常。
因此得出结论:以后再做除法+小数运算的时候 使用3个参数的divide(arg1,arg2,arg3)这个是最保险的。