众所周知,由于舍入和精度问题,比较浮点数是否相等有点棘手。
例如:比较浮点数,2012版
在Python中处理这个问题的推荐方法是什么?
有标准的库函数吗?
众所周知,由于舍入和精度问题,比较浮点数是否相等有点棘手。
例如:比较浮点数,2012版
在Python中处理这个问题的推荐方法是什么?
有标准的库函数吗?
当前回答
这对于你想要确保两个数字是相同的“达到精度”的情况很有用,并且不需要指定公差:
求这两个数的最小精度 将两者舍入到最小精度并进行比较
def isclose(a, b):
astr = str(a)
aprec = len(astr.split('.')[1]) if '.' in astr else 0
bstr = str(b)
bprec = len(bstr.split('.')[1]) if '.' in bstr else 0
prec = min(aprec, bprec)
return round(a, prec) == round(b, prec)
如上所述,它只适用于字符串表示中没有'e'的数字(意思是0.999999999999995e -4 < number <= 0.99999999999999995e11)
例子:
>>> isclose(10.0, 10.049)
True
>>> isclose(10.0, 10.05)
False
其他回答
使用Python的decimal模块,该模块提供decimal类。
评论如下:
值得注意的是,如果你 做繁重的数学工作,而你没有 绝对需要精准的 小数,这很麻烦 下来。浮点数要快得多 处理,但不精确。小数是 非常精确但很慢。
math.isclose()已为此添加到Python 3.5(源代码)。这里是它到Python 2的一个端口。它与Mark Ransom的单行程序的不同之处在于它可以正确地处理“inf”和“-inf”。
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
'''
Python 2 implementation of Python 3.5 math.isclose()
https://github.com/python/cpython/blob/v3.5.10/Modules/mathmodule.c#L1993
'''
# sanity check on the inputs
if rel_tol < 0 or abs_tol < 0:
raise ValueError("tolerances must be non-negative")
# short circuit exact equality -- needed to catch two infinities of
# the same sign. And perhaps speeds things up a bit sometimes.
if a == b:
return True
# This catches the case of two infinities of opposite sign, or
# one infinity and one finite number. Two infinities of opposite
# sign would otherwise have an infinite relative tolerance.
# Two infinities of the same sign are caught by the equality check
# above.
if math.isinf(a) or math.isinf(b):
return False
# now do the regular computation
# this is essentially the "weak" test from the Boost library
diff = math.fabs(b - a)
result = (((diff <= math.fabs(rel_tol * b)) or
(diff <= math.fabs(rel_tol * a))) or
(diff <= abs_tol))
return result
至于绝对误差,你可以检查一下
if abs(a - b) <= error:
print("Almost equal")
一些关于Python中浮动行为怪异的信息: Python 3教程03 - if-else,逻辑运算符和初学者常犯的错误
你也可以用数学。相对误差接近。
这对于你想要确保两个数字是相同的“达到精度”的情况很有用,并且不需要指定公差:
求这两个数的最小精度 将两者舍入到最小精度并进行比较
def isclose(a, b):
astr = str(a)
aprec = len(astr.split('.')[1]) if '.' in astr else 0
bstr = str(b)
bprec = len(bstr.split('.')[1]) if '.' in bstr else 0
prec = min(aprec, bprec)
return round(a, prec) == round(b, prec)
如上所述,它只适用于字符串表示中没有'e'的数字(意思是0.999999999999995e -4 < number <= 0.99999999999999995e11)
例子:
>>> isclose(10.0, 10.049)
True
>>> isclose(10.0, 10.05)
False
做一些像下面这样简单的事情就足够了:
return abs(f1 - f2) <= allowed_error