测试浮点数相等性
在Python中有没有一个函数可以用来测试浮点数是否大致相等?就像下面这样,
def approx_equal(a, b, tol):
return abs(a - b) < tol
我的需求类似于谷歌的C++测试库gtest.h中定义的EXPECT_NEAR
。
下面是一个例子:
def bernoulli_fraction_to_angle(fraction):
return math.asin(sqrt(fraction))
def bernoulli_angle_to_fraction(angle):
return math.sin(angle) ** 2
def test_bernoulli_conversions():
assert(approx_equal(bernoulli_angle_to_fraction(pi / 4), 0.5, 1e-4))
assert(approx_equal(
bernoulli_fraction_to_angle(bernoulli_angle_to_fraction(0.1)),
0.1, 1e-4))
6 个回答
8
在Python中有没有函数可以测试浮点数的近似相等性?
其实不可能有一个函数,因为这个定义是要根据具体情况来决定的。
def eq( a, b, eps=0.0001 ):
return abs(a - b) <= eps
这种方法并不总是有效。在某些情况下,
def eq( a, b, eps=0.0001 ):
return abs( a - b ) / abs(a) <= eps
可能会更合适。
另外,还有一种非常常见的方法。
def eq( a, b, eps=0.0001 ):
return abs(math.log( a ) - math.log(b)) <= eps
这可能会更合适。
我觉得很难要求一个函数能把所有数学上的选择都结合起来,因为这要看具体的应用场景。
19
另一种方法是计算两个数字的相对变化(或者叫相对差异),这个方法是用来比较两个数量时,考虑到它们的“大小”。在维基百科的文章中提到的两个公式可以在Python中用来进行比较,特别是当比较的值中有一个或两个是零时,这些公式也能处理这种情况:
def approx_equal(a, b, tol):
return abs(a-b) <= max(abs(a), abs(b)) * tol
def approx_equal(a, b, tol):
return abs(a-b) <= (abs(a)+abs(b))/2 * tol
无论哪种情况,计算出来的值都是一个没有单位的分数。在第一种情况下,基准值是两个数字中的最大绝对值,而在第二种情况下则是它们的平均绝对值。文章对这两种方法进行了更详细的讨论,包括它们的优缺点。如果在比较之前将后者乘以100,它就可以变成百分比差异(这时tol
就变成了一个百分比值)。需要注意的是,文章建议如果变化的值“本身就是一个百分比,那么最好用百分点来讨论它的变化”——也就是说,讨论绝对变化。
这两种方法(显然)比单纯计算两个数字的绝对差值要多一些计算,这一点可能需要考虑。
53
在比较数字时,可以使用 math.isclose
这个工具。
如果你想比较数字或者数组,可以用 numpy.allclose
。
而如果你需要测试数字或者数组是否相近,可以使用 numpy.testing.assert_allclose
。