【问题标题】:Why does assertAlmostEqual(-inf,-inf) fail?为什么 assertAlmostEqual(-inf,-inf) 失败?
【发布时间】:2011-03-21 11:15:14
【问题描述】:

Numpy 的 log 方法为 log(0) 提供 -inf。此值具有可比性:

>>> np.log(0) == np.log(0)
True

现在在单元测试中,以下工作正常:

self.assertEqual(np.log(0),np.log(0))

但这失败了:

self.assertAlmostEqual(np.log(0),np.log(0))

为什么会有这样的行为?这是一个错误还是有意的?如果需要,我如何检查两个浮点值是否几乎相等,并且对于 -inf 也能正常工作?

【问题讨论】:

    标签: python unit-testing numpy infinity


    【解决方案1】:

    来自 unittest 的文档,assertAlmostEqual(a, b) 默认等同于round(a-b, 7) == 0。所以在你的情况下你有:

    In [8]: np.log(0) - np.log(0)
    Out[8]: nan
    
    In [9]: round(np.log(0) - np.log(0), 7)
    Out[9]: nan
    
    In [11]: np.nan == 0
    Out[11]: False
    

    这解释了你的测试失败的原因。

    为了使它工作使用unittest2这里是一个例子:

    import unittest2
    import numpy as np
    
    class Test_Assertions(unittest2.TestCase):
        def test_float_inf(self):
            self.assertAlmostEqual(float('inf'), float('inf'))
    
        def test_numpy_inf(self):
            self.assertAlmostEqual(np.log(0),np.log(0))
    
    
    unittest2.main()
    

    输出:

    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK
    

    N.B:在 unittest2 assertAlmostEqual() 首先测试两个对象是否相等,如果是,那么结果是肯定的,否则做魔法(几乎相等),这就是它起作用的原因。它也应该在新的 python 版本(2.7 >)中工作,因为它们中的大多数都实现了 unittest2 功能(我不确定这一点,因为我的工作站中没有 python 2.7 >)。

    希望这可以帮助:)

    【讨论】:

      【解决方案2】:

      Inf 与任何有限值之间的差异是 Inf 或 -Inf。这是 IEEE754 规范的一部分。由于assertAlmostEqual 使用减法,这就解释了这种行为。

      这是英特尔 x86 文档中 FSUB 的相关表格:

      为了解决您的问题,您需要对 Inf 进行特殊情况处理。

      【讨论】:

      • 请注意,这种特殊情况属于assertAlmostEqual,而不是他的测试代码。这显然是TestCase.failUnlessAlmostEqual 中的一个错误。
      • @Glenn 我同意。我不知道如何提交 Python 错误报告!你呢?
      【解决方案3】:

      我会说 -∞ 和 -∞ 之间的差异可以达到 ∞。因此,它们并不是真正“几乎相等”。

      如果你想忽略这种特殊情况,那么这样的事情可能会有用:

      if valueA != valueB:
        self.assertAlmostEqual(valueA, valueB)
      

      【讨论】:

      • 它们是相等的,但不是几乎 [i.e.接近]相等?这没有意义。
      • @Devin:确实。不幸的是,IEEE 浮点数的极端情况(无穷大、NaN、+/-0)很少直观。 +/-0 是表现相当正常的罕见情况之一。
      • @Devin 确实有道理。例如。想一个很大的正数,x 说。现在平方 x。 x^2 小于无穷大,但距离 x 很远。现在考虑 x^x。它小于无穷大,但距离 x 更远。等等。这就是无限的本质。
      • @Devin:这个想法可能是两个都达到正无穷大的计算可以通过非常不同的计算到达那里。所以没有办法说是否意味着“相同的无限”。毕竟,无数个无限值。
      • @David @Joachim 但是如果两个数字之间有任何差异,它们就不相等。因此,如果差异很大,显然它是非零的,因此无穷大!=无穷大。然而无穷大==无穷大。上面的逻辑会暗示其他情况。