gpt4 book ai didi

Python Decimal 给出不正确的结果

转载 作者:行者123 更新时间:2023-12-05 02:18:14 24 4
gpt4 key购买 nike

我在进行以下计算时遇到问题:

Decimal(3)*(Decimal(1)/Decimal(3))

它返回的不是 1.0,而是 0.999...

无论我将 Decimal 模块的精度提高多少,情况仍然如此。

完整代码如下:

from decimal import Decimal
from decimal import getcontext
getcontext().prec = 800
print Decimal(3)*(Decimal(1)/Decimal(3))

具有讽刺意味的是,使用“原生”float 解决了这个问题:

print float(3)*(float(1)/float(3))

不用说,我在这里使用 Decimal 进行涉及大数求幂的更复杂的计算。遇到这个问题后,我设法将其最小化为上面的示例。

最佳答案

扩展一下我的评论:

Python 中的十进制数实际上就是您可以手写的那种数字。重要的是,它不理解递归的概念,因此像 1/3 这样的无限循环分数只是表示为 0.333333333333.. 直到你的精度点。当它乘以 3 时,你得到 0.99999.. - 这是明智的行为,因为它实际上不知道 0.33333333..1/3 被截断后。 Decimal 通常会因为除法时的舍入而失去精度(事实上,当除以 2 或 5 以外的任何因子时)。如果能够进行除法是至关重要的,请使用 Fraction,它表示任何有理数而不损失分子和分母的任何精度:

In [1]: from fractions import Fraction

In [2]: Fraction(3) * Fraction(1, 3)
Out[2]: Fraction(1, 1)

In [3]: print(_)
1

分数会自动化简。

对于您的 float ,我认为舍入误差自行抵消只是运气问题。请注意,floatDecimal 可能就足够了,除非您需要绝对 精度,在这种情况下我会推荐一个Fraction(例如,这意味着您可以可靠地进行相等性测试)。你总是可以四舍五入一个丑陋的数字,让它至少看起来更漂亮一点:

In [4]: "{:.2f}".format(Decimal(3) * (Decimal(1) / Decimal(3)))
Out[4]: '1.00'

如果您正在做类似模拟的事情,0.99999991 之间的差异通常实际上并不重要。

另一种选择是重新调整您的操作顺序,以便保证分子可以被分母整除,如阿尼尔库马尔的回答。如果可能的话,这是一个很好的解决方案,但在某些情况下您可能无法这样做——例如,您期望结果是小数,或者您从某种黑匣子中得到小数被乘数。此时,可以同时跟踪 Decimal 分子和分母。然后您会意识到这就是 Fraction 类所做的,而且麻烦更少。

请注意,您可以将 Fraction 用于 Decimal 可以做的任何事情,但更重要的是。任何可表示的十进制数也是分数(10 的某个幂的尾数)。例如:

In [2]: Fraction("3.141")
Out[2]: Fraction(3141, 1000)

自然地,这会导致一些性能损失 - 分数必须跟踪更多数据,进行更多计算并且可能更加抽象。

查看您新提供的公式 - 请注意,当您将有理数乘以非整数的幂时,结果可能不是有理数,因此您可能会在此过程中的某个地方丢失分数,例如:

>>> Fraction(1, 2) ** 4
Fraction(1, 16)
>>> Fraction(1, 2) ** 0.5
0.7071067811865476

尽管在计算公式的上下文中,尝试以符号方式存储所有内容并没有多大意义。这让我们回到了粗略的 float 通常就足够好的想法。如果你真的想要某种 surd 输出格式,你可以试试 sympy:

In [1]: from sympy import *

In [2]: sqrt(Integer(1) / Integer(2))
Out[2]: sqrt(2)/2

这当然会进一步降低您的速度。

关于Python Decimal 给出不正确的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46074244/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com