众所周知,由于舍入和精度问题,比较浮点数是否相等有点棘手。
例如:比较浮点数,2012版
在Python中处理这个问题的推荐方法是什么?
有标准的库函数吗?
众所周知,由于舍入和精度问题,比较浮点数是否相等有点棘手。
例如:比较浮点数,2012版
在Python中处理这个问题的推荐方法是什么?
有标准的库函数吗?
当前回答
我喜欢Sesquipedal的建议,但有修改(一个特殊的用例时,两个值都是0返回False)。在我的例子中,我使用的是Python 2.7,只使用了一个简单的函数:
if f1 ==0 and f2 == 0:
return True
else:
return abs(f1-f2) < tol*max(abs(f1),abs(f2))
其他回答
使用==是一个简单的好方法,如果你不关心公差精确。
# Python 3.8.5
>>> 1.0000000000001 == 1
False
>>> 1.00000000000001 == 1
True
但是要注意0:
>>> 0 == 0.00000000000000000000000000000000000000000001
False
0始终是0。
使用数学。如果你想控制公差,是接近的。
默认值a == b等价于数学。Isclose (a, b, rel_tol=1e-16, abs_tol=0)。
如果你仍然想使用==带有自定义容差:
>>> class MyFloat(float):
def __eq__(self, another):
return math.isclose(self, another, rel_tol=0, abs_tol=0.001)
>>> a == MyFloat(0)
>>> a
0.0
>>> a == 0.001
True
到目前为止,我没有找到任何地方配置它全局浮动。此外,mock也不能用于float.__eq__。
不带atol/rtol与给定小数进行比较:
def almost_equal(a, b, decimal=6):
return '{0:.{1}f}'.format(a, decimal) == '{0:.{1}f}'.format(b, decimal)
print(almost_equal(0.0, 0.0001, decimal=5)) # False
print(almost_equal(0.0, 0.0001, decimal=4)) # True
Python 3.5增加了数学运算。Isclose和cmath。isclose函数如PEP 485所述。
如果您使用的是较早版本的Python,相应的函数在文档中给出。
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
Rel_tol是一个相对容差,它乘以两个参数的大小中较大的一个;当值变大时,它们之间允许的差异也会变大,但仍然认为它们相等。
Abs_tol是在所有情况下按原样应用的绝对容差。如果差值小于这些公差中的任何一个,则认为值相等。
我发现下面的比较很有帮助:
str(f1) == str(f2)
我喜欢Sesquipedal的建议,但有修改(一个特殊的用例时,两个值都是0返回False)。在我的例子中,我使用的是Python 2.7,只使用了一个简单的函数:
if f1 ==0 and f2 == 0:
return True
else:
return abs(f1-f2) < tol*max(abs(f1),abs(f2))