double値のassertEqualsのイプシロン引数の意味


187

assertEqualsdouble値をテストするためのjunitについて質問があります。私が見ることができるAPIドキュメントを読む:

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

非推奨。代わりにassertEquals(doubleが必要、double actual、double epsilon)を使用してください

何をしないepsilon値の意味は?(イプシロンはギリシャ語のアルファベットの文字ですよね?)

誰かがそれを使用する方法を私に説明できますか?

回答:


198

イプシロンは、2つの数値をオフにすることができる値です。したがって、それがtrueである限り、Math.abs(expected - actual) < epsilon


3
それでは、イプシロンとしてどの値を渡す必要がありますか?
emeraldhieu 2015

15
@ Emerald214の精度。double値が0Dであることを表明したい場合、イプシロンは0になります(100%の精度、例外なし)。エラーのマージンが必要な場合(度など)、イプシロンを1に設定できます。たとえば、64.2°は64.8°と同じです(abs(64.8-64.2)<1であるため)
Pieter De Bie

3
ドキュメントには、「デルタ-両方の数値がまだ等しいと見なされる期待値と実際値の最大デルタ」と記載されています。だから私はそれがあるべきだと思い<=ません<
Andrew Cheong

コードを見ると、doubleIsDifferent(double値を比較するための)メソッドが呼び出され、が返されますMath.abs(d1 - d2) > delta。したがって、d1とd2の差がデルタよりも大きい場合は、値が異なり、trueを返します。値が等しいと見なされた場合はfalseを返します。そのメソッドは、assertEqualsで直接呼び出され、trueを返す場合、assertEqualsが呼び出されfailNotEquals、テストの結果は失敗になります。
anthomaxcool 2018年

1
@jbertたくさんの数値を平均化したり、標準偏差を計算したりするだけの場合、典型的なイプシロンのdouble値は誰かにアドバイスできますか?
simgineer

121

これはどのバージョンのJUnitですか?イプシロンではなくデルタのみを見たことがありますが、それは副次的な問題です!

JUnit javadocから:

デルタ-両方の数値がまだ等しいと見なされる、予想と実際の最大デルタ。

おそらくやり過ぎですが、通常は非常に小さい数を使用します。

private static final double DELTA = 1e-15;

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

あなたが使用している場合hamcrestのアサーションを、あなただけの標準を使用することができますequalTo()(それがデルタを使用していない)2倍に。ただし、デルタが必要な場合は、次のように使用できます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));
}

FYIの次のJUnit 5では、2つのdoubleを使用して呼び出すときにもデルタをオプションにしassertEquals()ます。実装は、(もし興味があるなら)です。

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

57

浮動小数点の計算は正確ではありません。丸め誤差や表現による誤差がよくあります。(たとえば、0.1は2進浮動小数点で正確に表すことができません。)

このため、2つの浮動小数点値が等しいかどうかを直接比較することは、計算方法によってはわずかに異なる場合があるため、通常はお勧めできません。

JDelta javadocsで呼び出される「デルタ」は、それらがまだ等しいと見なされるために許容できる値の差を表します。この値のサイズは、比較する値に完全に依存しています。doubleを比較するときは、通常、期待値を10 ^ 6で割った値を使用します。


11

問題は、浮動小数点数に固有の精度の問題により、2つのdoubleが正確に等しくない場合があることです。このデルタ値を使用すると、エラー要因に基づいて同等性の評価を制御できます。

また、一部の浮動小数点値には、NANや-Infinity / + Infinityなどの特殊な値があり、結果に影響を与える可能性があります。

2つのdoubleが完全に等しいことを本当に比較するつもりなら、長い表現としてそれらを比較するのが最善です

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

または

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

これらのニュアンスを考慮に入れることができます。

私は問題のAssertメソッドを掘り下げていませんが、以前のバージョンがこの種の問題で非推奨であり、新しいバージョンではそれらを考慮に入れているとしか想定できません。


2

イプシロンは間の差であるexpectedactualあなたはそれらが等しい考えて受け入れることができる値。.1たとえば設定できます。


2

計算を行わない場合でも、正確な浮動小数点値をアサートすることに問題はありません。例えば:

public interface Foo {
    double getDefaultValue();
}

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

この場合、それがMIN_VALUEゼロではないか-MIN_VALUEMIN_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
完全に等しいかどうかを確認する場合は、イプシロンを0.0に設定します。オブジェクトバリアントは必要ありません。
メルニコルソン2013年

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

浮動小数点数(floatやdoubleなど)を使用する場合、これは確実に機能しません。Javaの浮動小数点数がどのように格納され、算術演算がそれらに対してどのように機能するかを確認する必要がある場合があります。(ネタバレ:いくつかの丸め誤差が予想されます!)
Attila
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.