看这么一小段内容:
@Test
public void testDouble() {double a = 0.0000010;double b = 10.0;log.info("a * b = {}", a * b);
}
想要的是通过计算a*b后获取到的值应该是0.00001,但是实际上算出来的值是:
a * b = 9.999999999999999E-6
和我们想要的值计算出来的结果不一致,这是因为在Java中,浮点数计算可能会出现精度问题。
使用的double a = 0.0000010;是一个非常小的数,而double b = 10.0;是一个比较大的数。当你进行乘法运算时,a * b 的结果理论上应该是 0.00001。然而,浮点数在计算机内部以二进制存储,而并不是所有的十进制小数都能被精确表示。
由于这个表示的误差,再加上double的有限精度,计算结果可能不是期望的值,可能会出现误差,进而引发一些令人困惑的输出。
改进:
如果需要跟高精度的计算,可以使用BigDecimal,它能够精确表示和操作浮点数。
BigDecimal a1 = BigDecimal.valueOf(0.000010);
BigDecimal b1 = BigDecimal.valueOf(10.0);
BigDecimal c1 = a1.multiply(b1);
log.info("a1 * b1 = {}", c1);
得到想要的计算结果:
a1 * b1 = 0.0001000
这里不建议使用BigDecimal的构造方法来创建BigDecimal对象,因为在使用其构造方法创建对象时候,如果将double类型的数据转换为BigDecimal将会出现精度损失,推荐使用BigDecimal的valueOf()方法来创建BigDecimal对象。
BigDecimal bigDecimal = new BigDecimal(0.000001);
log.info("bigDecimal:{}", bigDecimal);
BigDecimal bigDecimal1 = BigDecimal.valueOf(0.000001);
log.info("bigDecimal1:{}", bigDecimal1);
上述创建对象时,new创建的对象取double值的时候,出现了精度损失的情况:
bigDecimal:9.99999999999999954748111825886258685613938723690807819366455078125E-7
bigDecimal1:0.0000010