在java中不管是float还是double在进行计算的时候都会有精度不准的问题如下例子:
@Test
public void test1() {
System.out.println(0.05 + 0.01);
System.out.println(1.0 - 0.42);
System.out.println(4.015 * 100);
System.out.println(123.2 / 100);
}
上述代码输出结果:
我们会发现实际结果会比我们想要的结果多,如果这样在进行对金钱的计算时就会出现多收或者少收的结果,这样肯定是有问题的
下面我们来说一下java里的BigDecimal类,这个类是java专门用于钱运算的类,先看下面例子:
@Test
public void test2() {
BigDecimal b1 = new BigDecimal(0.05);
BigDecimal b2 = new BigDecimal(0.01);
System.out.println(b1.add(b2));
}
上述代码输出结果:
可以看到使用Bigdecimal进行两个float或者double运算的时候还是会出现精度不准的问题。
进入Bigdecimal类查看它的double构造器:
/* The results of this constructor can be somewhat unpredictable.
* One might assume that writing {@code new BigDecimal(0.1)} in
* Java creates a {@code BigDecimal} which is exactly equal to
* 0.1 (an unscaled value of 1, with a scale of 1), but it is
* actually equal to
* 0.1000000000000000055511151231257827021181583404541015625.
* This is because 0.1 cannot be represented exactly as a
* {@code double} (or, for that matter, as a binary fraction of
* any finite length). Thus, the value that is being passed
* <i>in</i> to the constructor is not exactly equal to 0.1,
* appearances notwithstanding.
*/
官方注释说明了BigDecimal的double构造器会出现不可预测的问题
下面就来看一下另外一个BigDecimal构造器String构造器。
先看官方注释:
/*
* <p><b>Examples:</b><br>
* The value of the returned {@code BigDecimal} is equal to
* <i>significand</i> × 10<sup> <i>exponent</i></sup>.
* For each string on the left, the resulting representation
* [{@code BigInteger}, {@code scale}] is shown on the right.
*/
而String构造器就不会出现不可预测的问题
例子:
@Test
public void test3() {
BigDecimal b1 = new BigDecimal("0.05");
BigDecimal b2 = new BigDecimal("0.01");
System.out.println(b1.add(b2));
}
上述代码输出结果: