program story

부동 소수점이 부정확하기 때문에 Unittest (때때로)가 실패합니다.

inputbox 2020. 12. 8. 08:01
반응형

부동 소수점이 부정확하기 때문에 Unittest (때때로)가 실패합니다.


3 차원 공간의 점을 나타내는 벡터 클래스가 있습니다 . 이 벡터에는 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().


1) 테스트가 작동하는지 어떻게 확인할 수 있습니까?

사용 assertAlmostEqual, assertNotAlmostEqual.

로부터 공식 문서 :

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

차이를 계산하고 주어진 소수점 이하 자릿수 (기본값 7)로 반올림 한 다음 0과 비교하여 첫 번째와 두 번째가 거의 같은지 테스트합니다.

2) 대략적인 값을 테스트하지 않고 할 수 있습니까?

본질적으로 아니요.

부동 소수점 문제는 당신이 주어진다 "라운드"결과에 어느 그래서, 우회 할 수없는 vec.normalize또는 거의-동일한 결과를 받아 (둘 중 각각의 하나는 근사치입니다).


부동 소수점 값을 사용하면 가능한 작은 부정확성을 허용합니다. 따라서 테스트는 계산 된 값이 다음과 같이 허용 가능한 범위에 속하는지 테스트해야합니다.

theoreticalValue - epsilon < normalizedValue < theoreticalValue + epsilon

어디 epsilon당신이 때문에 부동 소수점 부정확성에 변형 허용으로 정의하는 것이 매우 작은 값이다.


한 가지 가능성은 모든 입력, 모든 중간 계산의 결과 및 출력이 정확히 표현 가능한 테스트 케이스에 함수를 적용하는 것 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

이것이 얼마나 실용적인지 잘 모르겠습니다 ...


일반적으로 float에 대해 동등성을 주장해서는 안됩니다. 대신 결과가 특정 범위 내에 있는지 확인하십시오. 예 :

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

참고 URL : https://stackoverflow.com/questions/8929005/unittest-sometimes-fails-because-floating-point-imprecision

반응형