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


187

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

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

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

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

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

답변:


198

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


3
엡실론으로 어떤 가치를 전달해야합니까?
emeraldhieu

15
@ Emerald214 정밀도의 양. double 값이 0D라고 주장하려면 엡실론은 0이됩니다 (100 % 정확도, 예외는 없음). 오차 한계 (도)를 원한다면 엡실론을 1로 설정할 수 있습니다. 예를 들어, 64.2 °는 64.8 °와 같습니다 (abs (64.8-64.2) <1부터)
Pieter De Bie

3
문서는 "델타-두 숫자가 여전히 동일한 것으로 간주되는 예상과 실제 사이의 최대 델타" 라고 말합니다 . 내가 생각하는 그래서 그은을해야 <=하지 <.
Andrew Cheong

코드를 살펴보면 메소드를 호출하여 doubleIsDifferent(이중 값을 비교하기 위해)를 반환합니다 Math.abs(d1 - d2) > delta. 따라서 d1과 d2의 차이가 델타보다 높으면 값이 다르고 true를 반환한다는 의미입니다. 값이 동일한 것으로 간주되면 false를 반환합니다. 이 메소드는 assertEquals에서 직접 호출되며 true를 리턴하면 assertEquals가 호출 failNotEquals되고 테스트 결과는 실패합니다.
anthomaxcool

1
@jbert 많은 숫자를 평균화하거나 표준 편차를 수행하는 경우 일반적인 엡실론 이중 값이 무엇인지 조언 할 수 있습니까?
simgineer

121

이 버전의 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);
}

57

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

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

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


11

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

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

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

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

또는

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

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

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


2

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


2

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

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));

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


7
정확히 같은지 확인하려면 epsilon을 0.0으로 설정하십시오. 오브젝트 변형이 필요하지 않습니다.
Mel Nicholson

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

부동 소수점 숫자 (float 또는 double과 같은)를 사용하면 안정적으로 작동하지 않습니다. Java의 부동 소수점 숫자가 저장되는 방법과 산술 연산이 어떻게 작동하는지 검토 할 수 있습니다. (스포일러 : 반올림 오류가 예상됩니다!)
Attila
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.