在java中,以下表达式结果为
new Double(1.0E22) + new Double(3.0E22) = 4.0E22
但
new Double(1.0E22) + new Double(4.0E22) = 4.9999999999999996E22
我期待它是5.0E22
。双倍极限是1.7976931348623157E308
。感谢你的帮助。我机器的架构是 x64,JVM 也是 64 位的。
欢迎来到浮点单元的星球。不幸的是,在现实世界中,您必须放弃一些精度才能获得速度和表示的广度。你无法避免:double
只是一个近似的表示。实际上,您不能以有限的精度表示数字。尽管如此,这是一个很好的近似值:小于 0.00000000001% 的误差。double
这与上限无关,而与 CPU 限制无关,请尝试使用 Python 进行更多数学运算:
>>> 4.9999999999999996 / 5.
1.0
>>> 5. - 4.9999999999999996
0.0
看?作为旁注,永远不要检查 上的相等性double
,使用近似相等:
if ((a - b) < EPSILON)
哪里EPSILON
是一个很小的值。可能 Java 库有更合适的东西,但你明白了。
如果您对某些理论感兴趣,浮点运算的标准是IEEE754
有几种方法可以减少浮点错误,例如pairwise summation和Kahan summation,但是这些都不能帮助你精确地表示像 5.0E22 这样的数字 - 正如 Stefano Sanfilippo 在他的回答中所说的那样,这是由于什么的限制您可以使用浮点表示,而不是用于实现答案的算法的问题。要表示 5.0E22,您应该使用BigDecimal或使用具有Rational
数据类型的库,例如JScience。