众所周知,由于舍入和精度问题,比较浮点数是否相等有点棘手。
例如:比较浮点数,2012版
在Python中处理这个问题的推荐方法是什么?
有标准的库函数吗?
众所周知,由于舍入和精度问题,比较浮点数是否相等有点棘手。
例如:比较浮点数,2012版
在Python中处理这个问题的推荐方法是什么?
有标准的库函数吗?
当前回答
如果你想在测试或TDD上下文中使用pytest包,下面是如何做到的:
import pytest
PRECISION = 1e-3
def assert_almost_equal():
obtained_value = 99.99
expected_value = 100.00
assert obtained_value == pytest.approx(expected_value, PRECISION)
其他回答
I'm not aware of anything in the Python standard library (or elsewhere) that implements Dawson's AlmostEqual2sComplement function. If that's the sort of behaviour you want, you'll have to implement it yourself. (In which case, rather than using Dawson's clever bitwise hacks you'd probably do better to use more conventional tests of the form if abs(a-b) <= eps1*(abs(a)+abs(b)) + eps2 or similar. To get Dawson-like behaviour you might say something like if abs(a-b) <= eps*max(EPS,abs(a),abs(b)) for some small fixed EPS; this isn't exactly the same as Dawson, but it's similar in spirit.
使用Python的decimal模块,该模块提供decimal类。
评论如下:
值得注意的是,如果你 做繁重的数学工作,而你没有 绝对需要精准的 小数,这很麻烦 下来。浮点数要快得多 处理,但不精确。小数是 非常精确但很慢。
我发现下面的比较很有帮助:
str(f1) == str(f2)
我同意Gareth的答案可能是最合适的轻量级函数/解决方案。
但我认为,如果您正在使用NumPy或正在考虑使用NumPy,那么有一个打包的函数用于此,这将是有帮助的。
numpy.isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
不过有一点免责声明:根据您的平台,安装NumPy可能是一种非常重要的体验。
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