我遇到以下计算问题:
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
进行更复杂的计算,涉及大数的取幂。遇到这个问题之后,我设法将它最小化到上面的例子。
谢谢。
答案 0 :(得分:4)
在我的评论中稍微扩展一下:
Python中的十进制数字实际上是您可能手写的数字。重要的是,它并不理解递归的概念,因此像1 / 3
这样的无限重复分数只表示为0.333333333333..
,直到精度为止。如果将此值乘以3,则会得到0.99999..
- 这是明智的行为,因为在0.33333333..
被截断后1 / 3
实际上已知道Decimal
为Fraction
。 In [1]: from fractions import Fraction
In [2]: Fraction(3) * Fraction(1, 3)
Out[2]: Fraction(1, 1)
In [3]: print(_)
1
经常因为四舍五入而失去精确度(事实上当你除以2或5以外的因子时)。如果能够进行除法是至关重要的,请使用float
,它代表任何有理数,而不会因分子和分母而失去任何精度:
Decimal
分数会自动简化。
随着你的浮动,我认为这是一个幸运的问题,舍入错误已经取消了。请注意,除非您需要绝对精度,否则Fraction
或In [4]: "{:.2f}".format(Decimal(3) * (Decimal(1) / Decimal(3)))
Out[4]: '1.00'
可能已经足够好了,在这种情况下我会推荐0.9999999
(例如,这意味着你可以可靠地进行平等测试)。你总是可以围绕一个丑陋的数字,使它至少看起来更漂亮:
1
如果你正在做类似模拟的事情,那么Decimal
和Fraction
之间的差异通常会真正重要。
另一个选择是重新调整你的操作顺序,以便保证分子可被分母整除,如下所示
Anilkumar的回答。如果可能的话,这是一个很好的解决方案,但有时你可能无法做到这一点 - 例如你期望结果是分数的,或者你得到一些分数乘数一种黑盒子。此时,可以跟踪Fraction
分子和分母......然后你就会意识到Decimal
类的作用是什么,但麻烦少了。
请注意,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
可以执行的操作,但更重要的是。任何可表示的十进制数也是一个分数(尾数超过10的幂)。例如:
sympy
当然,这会导致一些性能下降 - 分数必须跟踪更多数据,进行更多计算,并且可能更抽象。
看一下你新提供的公式 - 要小心当你将一个有理数提高到一个非整数的幂时,结果可能不合理,所以你可能会在某个地方失去分数,例如:
In [1]: from sympy import *
In [2]: sqrt(Integer(1) / Integer(2))
Out[2]: sqrt(2)/2
虽然在评估公式的背景下,尝试以符号方式存储所有内容并不是很有意义。这让我们回到粗略index.html:18 GET http://0.0.0.0:35729/livereload.js?snipver=1 net::ERR_CONNECTION_REFUSED
system.js:4 GET http://localhost:8000/src/main.ts 404 (Not Found)
Error: (SystemJS) Error: XHR error (404 Not Found) loading http://localhost:8000/src/main.ts
Error loading http://localhost:8000/src/main.ts
经常足够好的想法。如果你真的想要某种surd输出格式,你可以给{{1}}一个镜头:
{{1}}
这当然会减慢你的速度。
答案 1 :(得分:0)
我认为要改变禁忌症:
from decimal import Decimal
from decimal import getcontext
getcontext().prec = 800
print (Decimal(3)*Decimal(1))/Decimal(3)
对于我来说,对于一个
,输出为1