【发布时间】:2013-12-03 14:54:51
【问题描述】:
每个人都知道,或者至少,every programmer should know,使用 float 类型可能会导致精度错误。但是,在某些情况下,精确的解决方案会很好,并且在某些情况下使用 epsilon 值进行比较是不够的。无论如何,这不是重点。
我知道 Python 中的 Decimal 类型,但从未尝试过使用它。它指出"Decimal numbers can be represented exactly",我认为这意味着一个聪明的实现,它允许表示任何实数。我的第一次尝试是:
>>> from decimal import Decimal
>>> d = Decimal(1) / Decimal(3)
>>> d3 = d * Decimal(3)
>>> d3 < Decimal(1)
True
非常失望,我回到文档并继续阅读:
算术的上下文是指定精度的环境 [...]
好的,所以实际上有一个精度。并且经典问题可以复现:
>>> dd = d * 10**20
>>> dd
Decimal('33333333333333333333.33333333')
>>> for i in range(10000):
... dd += 1 / Decimal(10**10)
>>> dd
Decimal('33333333333333333333.33333333')
所以,我的问题是:有没有办法让 Decimal 类型具有无限精度?如果不是,那么比较 2 个十进制数的更优雅的方法是什么(例如,如果 delta 小于精度,d3
目前,当我只做除法和乘法时,我使用Fraction 类型:
>>> from fractions import Fraction
>>> f = Fraction(1) / Fraction(3)
>>> f
Fraction(1, 3)
>>> f * 3 < 1
False
>>> f * 3 == 1
True
这是最好的方法吗?还有什么其他选择?
【问题讨论】:
-
你想如何用你假设的 Decimal 类型来表示
Pi? -
@J.F.Sebastian 如果不可能,我不会感到惊讶。这就是为什么我要问“比较 2 个十进制数字的更优雅的方法是什么”。
-
我也在考虑一种允许许多操作(基本操作、常用功能等)但保持精确表示的类型。例如,Fraction 类型似乎可以处理很多情况。事实上,任何时候的结果都不是无理数。但也许我们可以使用包含更大子集的另一种表示来做得更好。例如,像孩子一样在学校会做的具有动态精度的事情。当然我不能代表
Pi,但很多时候,Pi只是问题的一个常数。 -
在你重新发明轮子之前,先看看 Sage 或 sympy
标签: python python-3.x floating-point decimal