2015-08-14 28 views
6

Dlaczego Java jest niekonsekwentny przy porównywaniu -0,0 i +0,0? Jaka jest standardowa metoda Java do porównywania liczb do konta -0/+ 0?Java - porównanie zera dodatniego i ujemnego

ja spotkałem tę szczególną Bugaboo:

public class ZeroCompare { 
    public static void main(String[] args) { 
     if (0.0 == -0.0) { 
      System.out.println("== --> same"); 
     } else { 
      System.out.println("== --> different"); 
     } 

     if (new Double(0.0).equals(-0.0)) { 
      System.out.println("equals --> same"); 
     } else { 
      System.out.println("equals --> different"); 
     } 
    } 
} 

Drukuje następujące:

== --> same 
equals --> different 

zdecydowanie nie podoba się fakt, że jak można porównać te dwie wartości wpływa na wynik, a ja kocham dla wyjaśnienia.

+0

pierwsze dosłowne równych wewnątrz (-0.0) jest nie Float podwójnie. a druga metoda równości porównuje obiekty, a dla różnych literałów są różne obiekty owijki. –

+1

@amitmahajan To podwójne. Wymagałoby to, aby 'f' lub' F' na końcu było literałem float. – Kayaman

+0

Nawiasem mówiąc, liczby zmiennoprzecinkowe nie są nigdy porównywane dla dokładnej równości. Wymagają małej wartości delta, aby sprawdzić, czy dwie liczby są wystarczająco blisko, aby można je było uznać za równe (chociaż w tym konkretnym przypadku jest to niewielki problem). – Kayaman

Odpowiedz

10

To zachowanie jest actually documented:

Jeżeli D1 oznacza +0.0 -0.0 natomiast D2 oznacza, lub vice versa, równy badana ma wartość fałszywą, chociaż +0.0 == - 0.0 ma wartość prawdziwą . Ta definicja umożliwia poprawne działanie tabel mieszających.

+0

Ładne małe zastrzeżenia w Javadoc ... – Kayaman

+0

Dzięki za link. Kiedy googlowałem, miałem początkowo nadzieję, że dociągnięty zostanie dokument java. Ale najwyraźniej Google znajduje stackoverflow znacznie bardziej popularny. – Curds

+1

Nie wiem, czy zgadzam się z ustaleniem Javy, że to "pozwala na poprawne działanie tabel mieszających" Wyobraź sobie, że mam wartości zmiennoprzecinkowe (32- lub 64-bitowe), których używam jako klucza w mapie skrótu (Dziwne, wiem ... To jest przykład.) Załóżmy, że mój kod działa z floatami, ale zawiera hasze Floats. Z powodu autoboxingu mogę bezpośrednio indeksować z floatem. Poza mapą skrótu, 0.0 i -0.0 porównałoby to samo - ale utworzyłoby dwa różne wpisy na mapie skrótów. Python idzie w drugą stronę; ponieważ 0,0 i -0,0 są uważane za "równe", mają one takie samo znaczenie. Myślę, że wolę to. – Curds

1

Java Language Specification: Numerical Comparison Operators <, <=, >, and >=

Pozytywne i negatywne zerowy zerowy są uważane za równe.

Double.valueOf (+0,0) i Double.valueOf (-0,0) mają różne reprezentacje bitów. Double.equals porównuje reprezentację bitową.

Również można użyć Double.compare

+0

Jestem zaskoczony, że reprezentacja bitów podwójnych +/- 0.0 jest inna niż reprezentacja pierwotna. Zawsze zakładałem, że jest to po prostu obiektowe opakowanie, więc możesz wprowadzić prymityw do kolekcji. To powiedziawszy, nawet jeśli bitowa reprezentacja wartości bazowej była identyczna z prymitywną (co jak przypuszczam), metoda "równa się" nie jest w żaden sposób związana ani kształtem ani formą użycia operatora == do określenia równości. To jest swego rodzaju punkt. – Curds

+0

Reprezentacja różni się także w typie pierwotnym, ale specyfikacja języka Java mówi, że operatory (><...) nie używają bit do porównania bitów. – sibnick