测试浮点相等

Nei*_*l G 36 python floating-point comparison

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

 def approx_equal(a, b, tol):
     return abs(a - b) < tol
Run Code Online (Sandbox Code Playgroud)

我的用例类似于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))
Run Code Online (Sandbox Code Playgroud)

Nei*_*l G 51

  • 为了比较数字,从Python 3.5开始math.isclose按照PEP 485.
  • 为了比较数字或数组,有numpy.allclose.
  • 对于测试数字或数组,有 numpy.testing.assert_allclose

  • 这实际上只是重定向到unittest的assertAlmostEqual,所以即使你没有使用鼻子也可以使用它. (17认同)

mar*_*eau 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
Run Code Online (Sandbox Code Playgroud)

两种情况下的计算值都是无单位分数.在第一种情况下,基线值是两个数字的最大绝对值,在第二种情况下,它是它们的平均绝对值.本文将更详细地讨论每个问题以及它们的优缺点.如果在比较之前乘以100(后者变为百分比值),后者可以变成百分比差异tol.请注意,该文章建议,如果变化值"本身就是一个百分比,那么最好通过使用百分点来讨论它的变化" - 即绝对变化.

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


S.L*_*ott 8

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

不能功能,因为定义取决于上下文.

def eq( a, b, eps=0.0001 ):
    return abs(a - b) <= eps
Run Code Online (Sandbox Code Playgroud)

并不总是有效.有些情况下

def eq( a, b, eps=0.0001 ):
     return abs( a - b ) / abs(a) <= eps
Run Code Online (Sandbox Code Playgroud)

可能更合适.

此外,总是很受欢迎.

def eq( a, b, eps=0.0001 ):
    return abs(math.log( a ) - math.log(b)) <=  eps
Run Code Online (Sandbox Code Playgroud)

哪个可能更合适.

我看不出你如何能要求一个(单)功能做结合所有数学的替代品.因为它取决于应用程序.

  • 不指定任意epsilon值.这是定义的:`来自sys.float_info import epsilon` (5认同)
  • 既然他必须自己实施它,他不能​​只为他的应用适当地实施它吗?你基本上是用一个问题来回答他的问题. (4认同)

Raf*_*ler 5

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

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

approx_equal = lambda a, b, t: abs(a - b) < t
Run Code Online (Sandbox Code Playgroud)

  • @Rafe Kettler - 是的,但把它想象成麻醉剂.当然,你爱他们.但有一天,你会在自己的汗水池中的混凝土地板上醒来,想一想"为什么这段代码只有在我向后看时才有意义?" (10认同)
  • 没有理由在这里使用lambda,没有为较短的代码授予分数,并且它是完全相同的代码.你甚至给它起了个名字...... (4认同)