测试浮点相等

时间:2010-10-26 23:38:38

标签: python comparison floating-point

是否有在python中测试浮点近似相等的函数?像,

 def approx_equal(a, b, tol):
     return abs(a - b) < tol

我的用例类似于Google的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 个答案:

答案 0 :(得分:51)

  • 为了比较数字,自Python 3.5起,每PEP 485就有math.isclose
  • 为了比较数字或数组,有numpy.allclose
  • 对于测试数字或数组,有numpy.testing.assert_allclose

答案 1 :(得分:19)

另一种方法是计算两个数字的relative change(或相对差异),“用于比较两个数量,同时考虑被比较事物的'大小'”。维基百科文章中提到的两个formulas可用于比较,如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,后者可以变成percentage differencetol变为百分比值)。请注意,文章建议如果变化值“本身就是一个百分比,最好通过使用百分点来谈论它的变化” - 即绝对变化。

这两种方法(显然)需要比简单地取两个数的差值的绝对值更多的计算,这可能是一个考虑因素。

答案 2 :(得分:8)

  

是否有在python中测试浮点近似相等的函数?

不能有 a 函数,因为定义取决于上下文。

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

哪个可能更合适。

我看不出你如何要求 a (单一)功能结合所有数学选择。因为它取决于应用程序。

答案 3 :(得分:5)

如果我是你,我只会使用您编写的内容,并将其放在一个单独的模块中(可能与您需要的其他实用程序,Python没有实现)或在任何代码要求的顶部它

您还可以使用lambda表达式(我最喜欢的语言功能之一,但可能不太清楚):

approx_equal = lambda a, b, t: abs(a - b) < t

答案 4 :(得分:4)

比较花车的平等性通常是一个坏主意。即使使用了您正在使用的容差功能,这也不是您想要做的。

如果你想使用浮点数,一个合理的选择就是重构你的算法以使用不等式a < b,因为这更有可能达到你的预期,假阴性或阳性更少,最重要的是,这意味着你不必猜测他们必须达到平等的程度。

如果你不能这样做,另一种选择是使用精确的表示。如果您的算法仅由算术运算(+-*/组成),那么您可以使用fractions.Fraction提供的合理重新定义,或者decimal.Decimal可能是你想要的(例如,财务计算)。

如果您的算法无法使用任意精度表示轻松表达,则另一种选择是使用区间运算明确管理舍入误差,例如使用this module

答案 5 :(得分:0)

根据the tutorial

  

...虽然数字不能接近预期的精确值,但round()函数可用于后舍入,因此不精确值的结果可以相互比较......

因此,这是我在Python中定义“isclose”函数的方式:

def isclose(a, b, ndigits):
   return round(a-b, ndigits) == 0

我通常使用5作为ndigits;但是,它取决于您期望的精度。