一般情况下,我们会使用double
或是float
来作为小数运算对象,不过因为浮点数的存储问题,导致了浮点数的精度丢失。
所以一般情况下,在需要精确计算时,我们会用到BigDecimal
。
参考资料: 知乎专栏
案例
以下是浮点数精度丢失的演示:
1 | System.out.println(0.06 + 0.01); |
预期的值应该是:
1 | 0.07 |
但运行下来得到的结果却是:
1 | 0.06999999999999999 |
这就是是因为浮点数末位精度问题,如果对以上的结果进行四舍五入的话就可以得到正确的值。
不过在使用中,我们还是更偏向于使用BigDecimal
。
BigDecimal
BigDecimal
我一般叫它大数
,从命名上就可以看出这个对象就是用来做大数字操作的。
使用方法可以是new BigDecimal()
,也可以是BigDecimal.valueOf()
。那么如果我们用下面的方式来进行浮点数运算是不是就没问题了呢?
1 | double d1 = 0.06; |
得到的结果是0.06999999999999999
,似乎和之前的错误结果是一样的。
这是因为BigDecimal
在接收浮点数时,同样会丢失精度。运行以下代码,可以看出问题:
1 | System.out.println(new BigDecimal(0.06)); |
得到的结果是:
1 | 0.059999999999999997779553950749686919152736663818359375 |
事实上,如果希望能精确地计算浮点数,需要使用String
字符串作转换,由BigDecimal
来生成浮点数。
1 | BigDecimal b1 = new BigDecimal("0.06"); |
这样才可以得到正确的结果:
1 | 0.06 |
总结
在一般的计算下,例如计算时间、里程等不需要非常精确的数值时,可以使用浮点数运算,并通过四舍五入达到预期结果。
在需要精确计算的情况下,例如金额、误差等情形,就可以使用BigDecimal
来运算,并且通过Double.toString()
方法将目标浮点数转化成String
字符串来达到预期。