为什么assertAlmostEqual(-inf,-inf)失败?

3 投票
3 回答
1614 浏览
提问于 2025-04-16 14:06

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))

为什么会出现这样的情况?这是个bug还是故意这样设计的?如果是故意的,我该如何检查两个浮点数值是否几乎相等,并且在处理负无穷大时也能正确工作呢?

3 个回答

3

我想说,负无穷大和负无穷大之间的差别可以达到正无穷大。所以,它们其实并不是“几乎相等”。

如果你想忽略这个特殊情况,那么下面这样的东西可能会对你有用:

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

无穷大(Inf)和任何有限值之间的差别要么是无穷大,要么是负无穷大。这是IEEE754标准的一部分。因为assertAlmostEqual这个函数是通过减法来比较的,所以就能解释它的表现。

下面是Intel x86文档中关于FSUB的相关表格:

enter image description here

要解决你的问题,你需要特别处理无穷大的情况。

5

根据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

注意:在unittest2中,assertAlmostEqual() 首先会检查两个对象是否相等,如果相等,结果就是相等;如果不相等,就会进行“魔法处理”(几乎相等),这就是它能工作的原因。它在新的Python版本(2.7及以上)中也应该能正常工作,因为大多数新版本都实现了unittest2的功能(我不太确定,因为我在工作站上没有安装Python 2.7及以上的版本)。

希望这对你有帮助 :)

撰写回答