2012-06-28 17 views
9

ja test JUnit stwierdzając dwa podwójne przedmiotów z:różnica Junit pomiędzy assertEquals (podwójne, podwójne) i assertEquals (dwukrotnie dwukrotnie, delta)

Assert.assertEquals(Double expected, Double result); 

To było dobrze wtedy zdecydował się na zmianę zamiast tego użyje prymitywnego double, który okazał się przestarzały, chyba że podasz deltę.

więc zastanawiam się, jaka jest różnica między używaniem obiektu Double lub typu pierwotnego w tym assertEquals? Dlaczego używanie obiektów bez delty jest ok, ale używanie elementów pierwotnych bez delty jest przestarzałe? Czy Java robi coś w tle, które ma już domyślną wartość delty?

Dzięki.

Odpowiedz

12

Jest NO assert method in JUnit z podpisem

assertEquals(Double expected, Double result); 

Jest jeden jednak rodzajowy dla obiektów:

assertEquals(Object expected, Object result); 

Wymaga equals metody obiektów i, jak można się spodziewać, że jest nie zaleca się tego do porównywania obiektów.

W przypadku gry podwójnej, jak zauważyłeś, absolutnie konieczne jest użycie delty do porównania, aby uniknąć problemów z zaokrąglaniem zmiennoprzecinkowym (wyjaśnione już w niektórych innych odpowiedziach). Jeśli korzystasz z wersji 3-argument assertEquals z double argumentów

assertEquals(double expected, double actual, double delta); 

twoi Double s dostanie cicho rozpakowanych do double i wszystko będzie działać dobrze (i twoje testy nie zawiedzie nieoczekiwanie :-).

+1

+1 re odprawa, tak, z zastrzeżeniem, że będziesz miał nieco inne zachowanie, jeśli jedno lub drugie podwójne jest zerowe. Dzięki obiektowi otrzymasz ładną wiadomość, z deltą otrzymasz wyjątek NullPointerException. –

+1

Moje doświadczenie jest takie, że te metody nie działają dobrze w przypadku bardzo dużych liczb w pewnych okolicznościach, szczególnie jeśli dane różnią się o kilka rzędów wielkości. Dwie liczby mogą mieć bardzo mały błąd procentowy, ale wymagają dopasowania do pozornie dużej delty. Ale ta sama delta nie zadziałałaby dla dużo mniejszych wartości w twoich danych. W niektórych przypadkach można oczekiwać, że nawet bardzo duże liczby będą pasować do niemal wszystkich cyfr znaczących. W innych przypadkach, na przykład podczas porównywania dwóch zoptymalizowanych algorytmów FFT, jest to znacznie mniej prawdopodobne. Bardziej niezawodną metodą jest ograniczenie błędu względnego. – orodbhen

+0

@orodbhen Aby to działało należy obliczyć delta na podstawie wykładnika wartości oczekiwanej, więc jeśli 'double e' jest wartością oczekiwaną, to delta powinna być' double d = Math.pow (10, Math.log10 (Math. abs (e)) - 12); 'gdzie' 12' to maksymalna praktyczna liczba cyfr znaczących. Jeśli pomnożysz log10 przez wartość <1.0, to test nie powiedzie się dla 'e' mającego duży dodatni wykładnik, a przeciwnie, jeśli pomnożysz log10 przez wartość> 1.0, to zawiedzie dla' e' mającego duży wykładnik ujemny - i to jest efekt, o którym pisałeś. Upewnij się więc, że delta dobrze pasuje do wykładnika wartości oczekiwanej. – Cromax

0

SOURCE. Zapewnia, że ​​dwa podwójne lub pływaki są równe wartości dodatniej delty. Jeśli nie, wywoływany jest błąd AssertionError. Jeśli oczekiwana wartość jest nieskończonością, wówczas wartość delta jest ignorowana. Liczba N jest uznawana za równą.

0

Powiedziałbym, że porównywanie podwójnych, pierwotnych lub obiektów, jest bezużyteczne bez delty. Wiedza na temat tego, jak działa liczba punktów płynących, jest kluczem do wykonania pracy numerycznej.

Obiekt może używać .equals pod pokrywami; prymityw nie ma opcji oprócz ==.

Tylko dlatego, że wersja obiektu nie używa delty, nie jest to lepszy pomysł.

5

Podwójna matematyka rzadko kiedy daje dokładnie równych wyników. Na przykład: 0.1 * 0.1 != 0.01. Zwykle potrzebujesz co najmniej trochę delty w porównywaniu wyników podwójnej precyzji.

Z drugiej strony, jeśli porównujesz zapakowane w pudełkach Double s, zakłada się, że chcesz dokładnie równości. Java nie uwzględnia domyślnej wartości delty, ale Double.equals ma nieco inne zachowanie niż ==: w szczególności its handling of NaNs.

to sens w testach, ponieważ Double.NaN != Double.NaN, ale w teście, jeśli oczekiwać NaN i NaN został zwrócony, to jest prawidłowa odpowiedź.

0

Lepiej napisać coś takiego:

assertEquals(23.0, 250.0, 0.0) 

0,0 - jest to trójkąt. Przeczytaj, dlaczego Twoje metody są przestarzałe.

Powiązane problemy