测试浮点数相等性

37 投票
6 回答
35782 浏览
提问于 2025-04-16 06:08

在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

撰写回答