我了解到我不能使用浮点类型(Java 中的 float/double)来进行货币计算
你不能用它double
来准确地代表超过 70 万亿美元的钱。对于小于此的值,您可以使用double
或long
没有错误(前提是您使用适当的舍入)
恕我直言double
,一旦您了解了舍入的必要性,使用起来就更简单了。
然而,许多人认为它容易出错,尤其是因为您不知道谁可能需要维护代码。使用 BigDecimal 将确保您正确使用舍入,并为您提供许多关于其工作方式的选项。
许多人发现令人不安的是,即使0.1
不是精确表示,BigDecimal 也可以显示精确表示(以及为什么您必须小心如何转换为 BigDecimal)
System.out.println(new BigDecimal(0.1));
印刷
0.1000000000000000055511151231257827021181583404541015625
许多低效使用
new BigDecimal(Double.toString(0.1))
或类似的东西,但具有讽刺意味的是,它只与他们试图避免使用的 toString 方法一样准确。
一种更有效的方法是
BigDecimal.valueOf(0.1)
这避免了创建字符串的需要。
支持的库double
将正确显示此数字,但一旦您执行计算,默认轮次可能还不够。
System.out.println(0.1 * 3);
印刷
0.30000000000000004
在这种情况下,您必须说出您期望的精度。假设你有美元和美分可以使用
System.out.printf("%.2f%n", 0.1 * 3); // round output to two decimal places
印刷
0.30
找到你不能再继续添加的地方 0.01
for (double d = 1; d < Long.MAX_VALUE; d *= 2) {
long l = Double.doubleToLongBits(d);
double d1 = Double.longBitsToDouble(l + 1);
if (d1 - d > 0.01) {
System.out.println("Cannot represent " + d + " plus 0.01");
double d_1 = Double.longBitsToDouble(l - 1);
if (d - d_1 < 0.01)
System.out.println("Can represent " + d + " minus 0.01");
break;
}
}
印刷
Cannot represent 7.0368744177664E13 plus 0.01
Can represent 7.0368744177664E13 minus 0.01