java中关于精度丢失的情况:
System.out.println(0.05 + 0.01); System.out.println(1.0 - 0.42); System.out.println(4.015 * 100); System.out.println(123.3 / 100);输出的结果为:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
----------------------------------------------------------------------------------------------------
而使用BigDecimal的String构造器
BigDecimal b1 = new BigDecimal("0.05"); BigDecimal b2 = new BigDecimal("0.01"); System.out.println(b1.add(b2));使用String构造器其结果为:0.06;
在BigDecimal源码中有说明:如果使用BigDecimal中double构造器,其运算结果会无限接近正确结果:
如:
BigDecimal b1 = new BigDecimal(0.05); BigDecimal b2 = new BigDecimal(0.01); System.out.println(b1.add(b2));
使用double构造器其结果为:0.06000000000000000298372437868010820238851010799407958984375,比结果大,既无限接近正确结果;
源码中的说明大概为:如果要使用double这个构造器,就要把参数使用Double的toString的方法(方法里面放double)转换为String,
然后使用BigDecimal(String)去构造,即:我们要用的话:要把double转为String,然后还要用BigDecimal的String构造器.
在价格运算应用中一定要用BigDecimal的String构造器;
封装成一个BigDecimalUtil:
public class BigDecimalUtil { private BigDecimalUtil() {} // + public static BigDecimal add(double v1, double v2) { //转换为String,然后就会调用String构造器 BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2); } // - public static BigDecimal sub(double v1, double v2) { //转换为String,然后就会调用String构造器 BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2); } // * public static BigDecimal mul(double v1, double v2) { //转换为String,然后就会调用String构造器 BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2); } // / public static BigDecimal div(double v1, double v2) { //转换为String,然后就会调用String构造器 BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); //要考虑除不尽的情况(更多需求需了解divide源码 return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);//四舍五入,保留两位小数 } }