单元测试(有时)失败,因为浮点不精确

时间:2012-01-19 15:49:14

标签: python unit-testing floating-point

我有一个 Vector 类,代表三维空间中的一个点。此向量有一个方法normalize(self, length = 1),可以向下/向上缩放向量为length == vec.normalize(length).length

由于浮点数不精确,此方法的单位测试有时失败。我的问题是,如何在正确实施方法时确保此测试不会失败?是否可以 不用 测试近似值?



其他信息

    def testNormalize(self):
        vec = Vector(random.random(), random.random(), random.random())
        self.assertEqual(vec.normalize(5).length, 5)

有时 会产生AssertionError: 4.999999999999999 != 5AssertionError: 5.000000000000001 != 5

注意:我知道浮点问题可能在Vector.length属性或Vector.normalize()中。

4 个答案:

答案 0 :(得分:100)

1)我如何确保测试有效?

使用assertAlmostEqualassertNotAlmostEqual

来自official documentation

assertAlmostEqual(first, second, places=7, msg=None, delta=None)

通过计算差值,舍入到给定的小数位数(默认值为7)并比较为零来测试第一个和第二个大致相等。

2)是否可以在不测试近似值的情况下进行?

基本上没有。

无法绕过floating point issue,因此您要么“舍入”vec.normalize给出的结果,要么接受几乎相等的结果(两者中的每一个都是近似值)。

答案 1 :(得分:3)

通过使用浮点值,您可以接受一个小的可能不精确。因此,您的测试应测试您的计算值是否落在可接受的范围内,例如:

theoreticalValue - epsilon < normalizedValue < theoreticalValue + epsilon

其中epsilon是一个非常小的值,您可以将其定义为由于浮点不精确而导致的变化。

答案 2 :(得分:1)

我认为有一种可能性是将函数应用于测试所有输入,所有中间计算的结果和输出都可由float精确表示的情况。

举例说明:

In [2]: import math

In [4]: def norm(x, y):
   ...:     return math.sqrt(x*x + y*y)
   ...: 

In [6]: norm(3, 4) == 5
Out[6]: True

不确定这是多么实用......

答案 3 :(得分:1)

通常,您不应声明浮点数的相等性。相反,请确保结果在某些范围内,例如:

self.assertTrue(abs(vec.normalize(5).length - 5) < 0.001)