단위 테스트에서 동등성을 위해 이중 값을 올바르게 비교하려면 어떻게해야합니까?


20

나는 최근에 시계열이 본질적으로 시계열 모듈을 설계했다 SortedDictionnary<DateTime, double>.

이제이 모듈이 항상 작동하고 예상 결과를 생성하는지 확인하기 위해 단위 테스트를 만들고 싶습니다.

일반적인 작업은 시계열의 포인트 간 성능을 계산하는 것입니다.

따라서 내가하는 일은 {1.0, 2.0, 4.0} (일부 날짜)로 시계열을 만드는 것이며 결과는 {100 %, 100 %} 일 것으로 예상합니다.

문제는 수동으로 {1.0, 1.0} 값으로 시계열을 만들고 각 점을 비교하여 동등성을 확인하면 실제 이진 표현으로 작업 할 때 항상 부정확성이 있기 때문에 테스트가 통과되지 않습니다. 번호.

따라서 다음 함수를 만들기로 결정했습니다.

private static bool isCloseEnough(double expected, double actual, double tolerance=0.002)
{
    return squaredDifference(expected, actual) < Math.Pow(tolerance,2);
}

그러한 경우를 다루는 또 다른 일반적인 방법이 있습니까?

답변:


10

이 문제를 처리하는 다른 두 가지 방법을 생각할 수 있습니다.

당신은 사용할 수 있습니다 Is.InRange:

Assert.That(result, Is.InRange(expected-tolerance, expected+tolerance));

당신은 사용할 수 있습니다 Math.Round:

Assert.That(Math.Round(result, sigDigits), Is.EqualTo(expected));

독자는 숫자가 예상 값과 비교되기 전에 숫자로 무슨 일이 일어나고 있는지 정확하게 볼 수 있기 때문에 두 가지 방법 모두 전용 함수보다 표현력이 있다고 생각합니다.


2
이 답변은 NUnit에만 해당되며 "제한 기반"어설 션 모델을 보여줍니다. 기본 어설 션 모델은 다음과 같습니다. Assert.AreEqual (expected, actual, tolerance);
RichardM

1
@RichardM : 답변으로 게시하고 수락하기로 선택합니다.
SRKX

@dasblinkenlight의 대답은 정확합니다. 세부 사항을 추가하면 명확하지 않을 수 있습니다 (클래식 어설 션 모델도 NUnit입니다). MSTest가 아닌 다른 테스트 프레임 워크에는 부동 소수점 값을 처리하기위한 자체 어설 션 모델이있을 수 있습니다.
RichardM

1
Assert.That(result, Is.InRange(expected-tolerance, expected+tolerance));경우 실패합니다 tolerance/abs(expected) < 1E-16.
quant_dev

@quant_dev 당신은 절대적으로 맞습니다. OP는 수익을 백분율로 계산하는 것에 대해 이야기하기 때문에 한 abs(expected)자리에서 두 자리 숫자로 가정합니다 . 또한 1E-9 부근에서 공차를 가정했습니다. 이러한 가정 하에서 이처럼 단순한 접근 방식은 합리적으로 잘 작동 할 수 있습니다 ( Is.InRange내 테스트에서 사용 ).
dasblinkenlight


3

그것은 당신이 숫자로 무엇을하는지에 달려 있습니다. 예를 들어 일부 기준에 따라 입력 세트에서 적절한 값을 선택해야하는 방법을 테스트하는 경우 엄격한 동등성을 테스트해야합니다. 부동 소수점 계산을 수행하는 경우 일반적으로 0이 아닌 공차로 테스트해야합니다. 공차의 크기는 계산에 따라 달라 지지만 배정 밀도를 사용하면 간단한 계산에는 1E-14 상대 공차를,보다 복잡한 계산에는 1E-8 (공차)를 선택하는 것이 좋습니다. 물론 YMMV이며 예상 결과가 0이면 약간의 절대 허용 오차를 추가해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.