如果你跟我一样以为Java的double类型只有在作乘除法时才会出现误差,那试一下在Java里执行一下下面的代码:

public static void  main(String[] args) {
    System.out.println(44.42 + 710.79 + 44.42 +  88.85);
}

执行前先猜一下结果,是会输出888.48么?还是……?

建议:对于和钱有关的计算,不论加减乘除,统一使用 BigDecimal!

然而不多久之后同事告诉我另一个BigDecimal的问题,试一下下面的代码:

System.out.println(new BigDecimal(0.99).setScale(2, RoundingMode.DOWN).toString());

结果是令人发指的0.98!

看了一下 BigDecimal(double)的源码,其中使用位操作分别提取了0.99浮点值的整数部分和纯小数部分,或者说是2的正数次幂和负数次幂部分。而这样提取出来的值纯小数部分本身就是近似的,与直接使用double类型没有本质区别,这是浮点表示法决定的,再经过2位截取后就产生了误差

而当使用BigDecimal(String)的构造器时得到的是精确值,因为该构造器将数字使用科学计数法表示,即 0.99表示为99*10^-2,这样做运算时先对齐至相同的整数位再进行计算

因此,对上面的补充是:如果要获取最精确的结果,请使用BD+字符串类型的构造器