[java] 더블 값에 대한 assertEquals의 엡실론 인수 의미

assertEquals이중 값을 테스트하기 위해 junit 에 대한 질문이 있습니다. API 문서를 읽으면 다음을 볼 수 있습니다.

@Deprecated
public static void assertEquals(double expected, double actual)

더 이상 사용되지 않습니다. 대신 assertEquals (더블 예상, 더블 실제, 더블 엡실론)를 사용하십시오.

epsilon가치는 무엇을 의미합니까? (엡실론은 그리스 알파벳 문자입니다.)?

누군가 나에게 사용법을 설명 할 수 있습니까?



답변

Epsilon은 2 개의 숫자를 해제 할 수있는 값입니다. 따라서 가능한 한 사실로 주장 할 것입니다.Math.abs(expected - actual) < epsilon


답변

이 버전의 JUnit은 무엇입니까? 나는 엡실론이 아닌 델타 만 본 적이 있지만 그것은 부수적 인 문제입니다!

JUnit javadoc에서 :

델타-두 숫자가 여전히 동일한 것으로 간주되는 예상과 실제 사이의 최대 델타.

아마 과잉일지도 모르지만, 나는 보통 아주 작은 숫자를 사용합니다

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertEquals(123.456, 123.456, DELTA);
}

당신이 사용하는 경우 hamcrest의 주장을, 당신은 단지 표준을 사용할 수 있습니다 equalTo()(이것은 델타를 사용하지 않는)이 더블로. 그러나 델타를 원한다면 closeTo()( javadoc 참조 )

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertThat(123.456, equalTo(123.456));
    assertThat(123.456, closeTo(123.456, DELTA));
}

참고로, 곧 출시 될 JUnit 5 는 두 개의 더블을 호출 할 때 델타를 옵션으로 만듭니다assertEquals() . 구현 (당신이 관심이 있다면)입니다 :

private static boolean doublesAreEqual(double value1, double value2) {
    return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2);
}


답변

부동 소수점 계산은 정확하지 않습니다. 반올림 오류와 표현으로 인한 오류가 종종 있습니다. 예를 들어 0.1은 이진 부동 소수점으로 정확하게 표현 될 수 없습니다.

이 때문에 두 부동 소수점 값이 동일한 지 직접 비교하는 것은 계산 방법에 따라 적은 양으로 다를 수 있으므로 일반적으로 좋은 생각이 아닙니다.

JUnit javadocs 에서 호출 된 “델타”는 여전히 동일한 것으로 간주되는 값에서 허용 할 수있는 차이의 양을 설명합니다. 이 값의 크기는 전적으로 비교하는 값에 따라 다릅니다. 복식을 비교할 때 일반적으로 예상 값을 10 ^ 6으로 나눈 값을 사용합니다.


답변

문제는 부동 소수점 숫자 고유의 정밀도 문제로 인해 두 개의 double이 정확히 같지 않을 수 있다는 것입니다. 이 델타 값을 사용하면 오차 계수를 기준으로 동등성 평가를 제어 할 수 있습니다.

또한 일부 부동 소수점 값에는 결과에 영향을 줄 수있는 NAN 및 -Infinity / + Infinity와 같은 특수 값이있을 수 있습니다.

두 복식이 정확히 같다는 것을 실제로 비교하려면 긴 표현으로 비교하는 것이 가장 좋습니다.

Assert.assertEquals(Double.doubleToLongBits(expected), Double.doubleToLongBits(result));

또는

Assert.assertEquals(0, Double.compareTo(expected, result));

이러한 뉘앙스를 고려할 수 있습니다.

나는 문제의 Assert 메소드에 대해 깊이 탐구하지 않았지만 이전 유형은 이러한 종류의 문제에 대해 더 이상 사용되지 않으며 새로운 것이 문제를 고려한다고 가정 할 수 있습니다.


답변

Epsilon은 값이 같다고 생각할 수있는 값 expectedactual값 의 차이 입니다. .1예를 들어 설정할 수 있습니다 .


답변

수학을하지 않으면 정확한 부동 소수점 값을 주장하는 데 아무런 문제가 없습니다. 예를 들어 :

public interface Foo {
    double getDefaultValue();
}

public class FooImpl implements Foo {
    public double getDefaultValue() { return Double.MIN_VALUE; }
}

이 경우 실제로 MIN_VALUE0이 아니 -MIN_VALUE거나 MIN_NORMAL매우 작은 값 인지 확인하고 싶습니다 . 당신은 말할 수 있습니다

double defaultValue = new FooImpl().getDefaultValue();
assertEquals(Double.MIN_VALUE, defaultValue);

그러나 이것은 당신에게 사용 중단 경고를 줄 것입니다. 이를 피하기 위해 assertEquals(Object, Object)대신 전화 를 걸 수 있습니다 .

// really you just need one cast because of autoboxing, but let's be clear
assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);

그리고 당신이 정말로 영리하게 보이고 싶다면 :

assertEquals(
    Double.doubleToLongBits(Double.MIN_VALUE), 
    Double.doubleToLongBits(defaultValue)
);

또는 Hamcrest 유창한 스타일 어설 션을 사용할 수 있습니다.

// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));

값이있는 거 확인이되면 않는 몇 가지 계산을 수행에서 온,하지만, 엡실론를 사용합니다.


답변

Assert.assertTrue(Math.abs(actual-expected) == 0)