打印下面这两个计算结果,得到的值可能和你预期的并不一样
System.out.println(0.1 + 0.2); System.out.println(1.0 - 0.8);
结果
0.30000000000000004 0.19999999999999996
之所以造成这种问题的主要原因就在于计算机无法精确表达某些数值,因此在涉及到金额计算的时,我们一般会使用BigDecimal来替代,不过它也存在一些需要特别注意的地方,否则一样会遇到一些令人匪夷所思的现象。
问题一:使用字符串类型的构造方法如果你使用double类型的构造方法做计算,同样存在精度问题
System.out.println(new BigDecimal(0.1).add(new BigDecimal(0.2)));
结果
0.3000000000000000166533453693773481063544750213623046875
请使用字符串类型的构造方法
System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.2")));
结果
0.3问题二:精度取舍方式
看出来了没,随着不同的参数值,其精度结果也不同
System.out.println(new BigDecimal("1.1").multiply(new BigDecimal("100")));
System.out.println(new BigDecimal("1.11").multiply(new BigDecimal("100")));
System.out.println(new BigDecimal("1.111").multiply(new BigDecimal("100")));
System.out.println("==================");
System.out.println(new BigDecimal("1.1").multiply(new BigDecimal(Double.toString(100))));
System.out.println(new BigDecimal("1.11").multiply(new BigDecimal(Double.toString(100))));
System.out.println(new BigDecimal("1.111").multiply(new BigDecimal(Double.toString(100))));
结果
110.0 111.00 111.100 ================== 110.00 111.000 111.1000
实际上这是因为scale和precision的原因,scale表示小数点之后的位数,precision表示精度,计算过程中传入不同的数值会直接影响scale和precision的数值,所以建议在计算时一定要显示的指定好期望的返回结果。
保留3位小数,剩下的直接舍弃
System.out.println(new BigDecimal("1.11").multiply(new BigDecimal("10")).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println(new BigDecimal("1.111").multiply(new BigDecimal("10")).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println(new BigDecimal("1.1111").multiply(new BigDecimal("10")).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println("==================");
System.out.println(new BigDecimal("1.11").multiply(new BigDecimal(Double.toString(10))).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println(new BigDecimal("1.111").multiply(new BigDecimal(Double.toString(10))).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println(new BigDecimal("1.1111").multiply(new BigDecimal(Double.toString(10))).setScale(3, BigDecimal.ROUND_DOWN));
结果
11.100 11.110 11.111 ================== 11.100 11.110 11.111问题三:比较
如果使用equals来进行比较,可能也得不到想要的结果,比如像下面这样,返回结果为false
System.out.println(new BigDecimal("1.0").equals(new BigDecimal("1")));
看看BigDecimal提供的equals方法说明就清楚了,它除了比较value,还会比较scale
Compares this {@code BigDecimal} with the specified
{@code Object} for equality. Unlike {@link
#compareTo(BigDecimal) compareTo}, this method considers two
{@code BigDecimal} objects equal only if they are equal in
value and scale (thus 2.0 is not equal to 2.00 when compared by
this method).
因此,如果我们只是希望比较value,则建议使用comparTo方法,其返回结果按照标准约定来,-1、0、1分别代表小于、等于、大于
System.out.println(new BigDecimal("1.0").compareTo(new BigDecimal("1")));



