为什么assertAlmostEqual(-inf,-inf)失败?
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的相关表格:
要解决你的问题,你需要特别处理无穷大的情况。
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及以上的版本)。
希望这对你有帮助 :)