1 回答
TA贡献1775条经验 获得超8个赞
电脑不是魔法。它们不能以无限精度表示数字,因为这需要不存在的无限内存。他们使用一种创造性的解决方案来尝试以一种涵盖您想要表示的大多数数字的方式来表示浮点数,同时它仍然适合 32 位(浮点数)或 64 位(双精度数)。但这确实意味着它不准确。双精度/浮点数实际上只能表示有限数量的特定数字,如果您试图让一个数字表示不是其中之一的数字,则会得到它可以表示的最接近它的数字。
那么,哪些数字可以表示,哪些不可以表示?这非常棘手,因为计算机以 2 为基数工作,而我们人类倾向于以 10 为基数进行思考。
这导致了两个重要的教训:
每当您“渲染”双精度或浮点数时,即向用户显示或出于任何其他原因将其转换为字符串时,您必须向计算机指定您要查找的内容。“只是打印它”不会做,如果你尝试这样做(例如,
System.out.println(someDouble);
计算机只是猜测,通常会猜错。这是正确的方法:System.out.printf("%.2f\n", someDouble)
或者如果你不想打印但转换为字符串,String.format("%.2f", someDouble)
:您告诉 java 打印/字符串化它,以便在逗号后最多获得 2 位数字。如果 2.7 表示为 2.6999999999999999852,它仍会打印 2.7,因为这是最接近的不超过 2 位数字-after-the-comma 字符串表示为 2.6999999999999999852。如果您希望保证精度(通常在处理金钱时是个好主意!!),根本不要使用 double 或 float。通常的解决方案是使用
int
或long
存储美分而不是欧元或美元。有些人会建议你BigDecimal
改用,但我建议不要这样做,除非你真的知道你需要它。分钱很棘手,需要自定义策略,甚至BigDecimal
不能在不四舍五入或崩溃的情况下将 4 美分分到 3 个银行账户。BigDecimal
当你必须乘以细节时,这是一个更合理的想法,这会带来很多外汇。在您的情况下,您需要应用增值税计算,不要理会它并坚持使用美分,存储在整数或多头中。
使用float
而不是时得到不同结果的原因double
是浮点数仅占用 32 位内存,因此float
与double
. Java 的 System.out.println 将应用一些四舍五入(但不多)。这种四舍五入往往不足以隐藏float
.
18.78998464050293
是与 的实际答案完全一致的最接近的数字18.789984000000004
。
添加回答
举报