扩展一下我的评论:
Python中的十进制数实际上就是您可以手工写下的数字。重要的是,它不理解递归的概念,所以像1 / 3这样的无限循环的分数在精度上只表示为0.333333333333..。当这乘以3,你得到0.99999..-这是合理的行为,因为它实际上不知道{}在被截断后是{}。Decimal在除法时,由于舍入(事实上,当你除以除2或5以外的任何因子时),s通常会失去精度。如果除法是至关重要的,那么使用Fraction,它代表任何有理数,而分子和分母不会损失任何精度:In [1]: from fractions import Fraction
In [2]: Fraction(3) * Fraction(1, 3)
Out[2]: Fraction(1, 1)
In [3]: print(_)
1
分数会自动简化。在
对于你的浮点数,我想这只是运气问题,舍入误差已经抵消了自己。注意,float或{}可能足够好,除非您需要绝对精度,在这种情况下,我建议使用Fraction(例如,这意味着您可以可靠地进行相等性测试)。你总是可以把难看的数字四舍五入,使它至少看起来漂亮一点:
^{pr2}$
如果你在做类似模拟的事情,0.9999999和{}之间的区别通常并不重要。在
另一个选择是重新排列操作顺序,这样分子就可以被分母整除,如中所示
阿尼尔库马尔的回答。如果可能的话,这是一个很好的解决方案,但是在某些情况下你很可能做不到这一点-比如你期望结果是分数的,或者你从某种黑匣子中得到分数被乘数。此时,可以同时跟踪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
这当然会让你慢下来。在