Właśnie studiowałem pytania OCPJP i znalazłem ten dziwny kod:
public static void main(String a[]) {
System.out.println(Double.NaN==Double.NaN);
System.out.println(Double.NaN!=Double.NaN);
}
Kiedy uruchomiłem kod, otrzymałem:
false
true
Jaki jest wynik, false
gdy porównujemy dwie rzeczy, które wyglądają tak samo? Co to NaN
znaczy?
In [1]: NaN==NaN Out[1]: False
Double.NaN==Double.NaN
powinno rzeczywiście zwrócić prawdę, gdybyDouble.NaN
były typujava.lang.Double
. Jednak jego typ jest prymitywnydouble
i obowiązują reguły operatoradouble
(które wymagają tej nierówności dla zgodności z IEEE 754, jak wyjaśniono w odpowiedziach).Odpowiedzi:
NaN oznacza „To nie jest liczba”.
Java Language Specification (JLS) Third Edition mówi :
źródło
false
. Tak więc ten standard różni się od Javy tym, że wymaga tego IEEE(NAN != NAN) == false
.NaN z definicji nie jest równe żadnej liczbie, w tym NaN. Jest to część standardu IEEE 754 i zaimplementowana przez CPU / FPU. Nie jest to coś, co JVM musi dodawać jakąkolwiek logikę do obsługi.
http://en.wikipedia.org/wiki/NaN
Java traktuje wszystkie NaN jako ciche NaN.
źródło
Skąd ta logika
NaN
znaczyNot a Number
. Co to nie jest liczba? Byle co. Możesz mieć wszystko po jednej stronie i wszystko po drugiej, więc nic nie gwarantuje, że oba są równe.NaN
jest obliczany za pomocąDouble.longBitsToDouble(0x7ff8000000000000L)
i jak widać w dokumentacjilongBitsToDouble
:Ponadto
NaN
jest logicznie traktowany wewnątrz interfejsu API.Dokumentacja
Nawiasem mówiąc,
NaN
jest testowany jako przykładowy kod:Rozwiązanie
Możesz użyć
compare
/compareTo
:Albo
equals
:źródło
NaN != NaN
fałszu uczyniłoby programy bardziej skomplikowanymi niż posiadanieNaN != NaN
prawdy? Wiem, że IEEE podjęło decyzję wieki temu, ale z praktycznego punktu widzenia nigdy nie widziałem przypadków, w których jest to przydatne. Jeśli operacja ma być wykonywana, dopóki kolejne iteracje nie dadzą tego samego wyniku, mając dwie kolejne iteracje, NaN byłby „naturalnie” wykrywany jako warunek wyjścia, gdyby nie to zachowanie.f(f(f...f(x)))
i znajdujey=f[n](x)
dla kogośn
taki, że wynikf(y)
jest nie do odróżnienia ody
, toy
będzie nie do odróżnienia od wyniku jakiegokolwiek głębiej zagnieżdżonegof(f(f(...f(y)))
. Nawet gdyby ktoś chciałNaN==NaN
być fałszywy, bycie fałszywymNan!=Nan
również byłoby mniej „zaskakujące” niżx!=x
bycie prawdziwym dla jakiegoś x.Double.NaN
nie jestDouble
, aledouble
więc pytanie dotyczy zachowaniadouble
. Chociaż istnieją funkcje, które mogą testować relację równoważności obejmującądouble
wartości, jedyną przekonującą odpowiedzią, jaką znam na pytanie „dlaczego” (która jest częścią pierwotnego pytania), jest „ponieważ niektórzy ludzie w IEEE nie sądzili, zdefiniować relację równoważności ”. Przy okazji, czy istnieje jakiś zwięzły idiomatyczny sposób testowaniax
iy
równoważności przy użyciu tylko operatorów pierwotnych? Wszystkie znane mi formuły są raczej niezgrabne.Może to nie jest bezpośrednia odpowiedź na to pytanie. Ale jeśli chcesz sprawdzić, czy coś jest równe
Double.NaN
, użyj tego:To wróci
true
źródło
Javadoc dla Double.NaN mówi wszystko:
Co ciekawe, źródło
Double
definiuje wNaN
ten sposób:Opisane przez ciebie specjalne zachowanie jest na stałe przypisane do maszyny JVM.
źródło
zgodnie ze standardem IEEE dla arytmetyki zmiennoprzecinkowej dla liczb Double Precision,
gdzie,
Co znaczy,
Jeśli wszystkie
E
bity mają wartość 1 i jeśli jest jakiś niezerowy bit,F
liczba wynosiNaN
.dlatego między innymi wszystkie kolejne liczby są
NaN
,W szczególności nie możesz testować
aby sprawdzić, czy dany wynik jest równy
Double.NaN
, ponieważ wszystkie wartości „niebędące liczbą” są traktowane jako różne. Możesz jednak skorzystać zDouble.isNaN
metody:źródło
NaN to specjalna wartość oznaczająca „nie jest liczbą”; jest wynikiem pewnych nieprawidłowych operacji arytmetycznych, takich jak
sqrt(-1)
, i ma tę (czasami irytującą) właściwośćNaN != NaN
.źródło
Brak liczby reprezentuje wynik operacji, których wyniku nie można przedstawić za pomocą liczby. Najbardziej znaną operacją jest 0/0, której wynik nie jest znany.
Z tego powodu NaN nie jest równe żadnemu (w tym innym wartościom niebędącym liczbą). Aby uzyskać więcej informacji, po prostu sprawdź stronę wikipedii: http://en.wikipedia.org/wiki/NaN
źródło
0/0
.0/0
jest zawsze NaN, ale NaN może być wynikiem innych operacji - takich jak2+NaN
:an operation that has no mathematically definite result produces NaN
zgodnie z odpowiedzią @AdrianMitevWedług tego linku ma różne sytuacje i trudno je zapamiętać. Tak je pamiętam i rozróżniam.
NaN
oznacza „matematycznie niezdefiniowany”, na przykład: „wynik dzielenia 0 przez 0 jest niezdefiniowany” i ponieważ jest niezdefiniowany, więc „porównanie związane z niezdefiniowanym jest oczywiście niezdefiniowane”. Poza tym działa bardziej jak przesłanki matematyczne. Z drugiej strony, zarówno dodatnia, jak i ujemna nieskończoność są predefiniowane i ostateczne, na przykład „dodatnia lub ujemna nieskończoność jest dobrze zdefiniowana matematycznie”.źródło