Double値をテストするjunit assertEquals
について質問があります。私が見ることができるAPIドキュメントを読む:
@Deprecated public static void assertEquals(double expected, double actual)
非推奨。代わりにassertEquals(double expected、double actual、double epsilon)を使用してください
epsilon
値の意味は何ですか? (イプシロンはギリシャ語のアルファベットの文字ですよね?)。
誰かがそれを使用する方法を説明できますか?
イプシロンは、2つの数値がオフになる値です。したがって、Math.abs(expected - actual) < epsilon
である限りtrueにアサートされます。
これはJUnitのどのバージョンですか?私はイプシロンではなくデルタを見たことがありますが、それは副次的な問題です!
JUnitから javadoc :
delta-両方の数値がまだ等しいと見なされる、期待される値と実際の値の間の最大の差。
おそらくやり過ぎですが、通常は非常に小さな数を使用します。
private static final double DELTA = 1e-15;
@Test
public void testDelta(){
assertEquals(123.456, 123.456, DELTA);
}
hamcrest アサーションを使用している場合は、標準のequalTo()
を2つのdoubleで使用できます(デルタは使用しません)。ただし、デルタが必要な場合は、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()
を呼び出すときに deltaをオプションにする にもなります。 実装 (興味がある場合):
private static boolean doublesAreEqual(double value1, double value2) {
return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2);
}
浮動小数点の計算は正確ではありません-多くの場合、丸め誤差と表現による誤差があります。 (たとえば、0.1は2進浮動小数点で正確に表すことはできません。)
このため、2つの浮動小数点値が等しいかどうかを直接比較することは通常、良い方法ではありません。計算方法によってはわずかに異なる場合があるためです。
「デルタ」は、JUnit javadocs で呼ばれるように、値がまだ等しいと見なされるために許容できる差の量を示します。この値のサイズは、比較する値に完全に依存します。 doubleを比較するとき、通常は期待値を10 ^ 6で割った値を使用します。
問題は、浮動小数点数に固有の精度の問題により、2つのdoubleが正確に等しくない場合があることです。このデルタ値を使用すると、エラー要因に基づいて同等性の評価を制御できます。
また、一部の浮動小数点値には、NANや-Infinity/+ Infinityのような特別な値があり、結果に影響を与える可能性があります。
2つのdoubleが正確に等しいことを本当に比較する場合、長い表現として比較するのが最善です。
Assert.assertEquals(Double.doubleToLongBits(expected), Double.doubleToLongBits(result));
または
Assert.assertEquals(0, Double.compareTo(expected, result));
これらのニュアンスを考慮することができます。
私は問題のAssertメソッドについて詳しく調べていませんが、この種の問題については以前のものが非推奨であり、新しいものはそれらを考慮に入れていると推測できます。
数学を行わない場合は、正確な浮動小数点値をアサートしても問題はありません。例えば:
public interface Foo {
double getDefaultValue();
}
public class FooImpl implements Foo {
public double getDefaultValue() { return Double.MIN_VALUE; }
}
この場合、ゼロまたはMIN_VALUE
または-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の流fluentなスタイルのアサーションを使用できます。
// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));
ただし、チェックしている値がdoesである場合は、イプシロンを使用します。
イプシロンは、expected
とactual
の値の違いであり、等しいと考えることができます。たとえば、.1
を設定できます。