Od apidoc, Float.compare
:
Porównuje dwie wartości określone pływaka. Znak wartości całkowita zwracana jest taka sama, jak w przypadku liczb całkowitych, które byłyby zwrócony przez wywołanie:
nowy float (f1) .compareTo (nowa Float (F2))
Float.compareTo
:
Porównuje dwa obiekty Float numerycznie. Istnieją dwa sposoby, w których porównania wykonywane za pomocą tej metody różnią się od tych wykonywanych przez język Java numerycznych operatorów porównania (<, < =, ==,> =>), gdy stosuje się do pierwotnych wartości float:
- Float. NaN jest przez tę metodę uznawany za równy sobie i większy niż wszystkie pozostałe wartości zmiennoprzecinkowe (w tym Float.POSITIVE_INFINITY).
- W tej metodzie wartość0,0f jest większa niż -0,0f.
Zapewnia to, że naturalna kolejność obiektów Float nałożonych tą metodą jest równa wartościom równym.
Rozważmy następujący kod:
System.out.println(-0.0f == 0.0f); //true
System.out.println(Float.compare(-0.0f, 0.0f) == 0 ? true : false); //false
System.out.println(Float.NaN == Float.NaN);//false
System.out.println(Float.compare(Float.NaN, Float.NaN) == 0 ? true : false); //true
System.out.println(-0.0d == 0.0d); //true
System.out.println(Double.compare(-0.0d, 0.0d) == 0 ? true : false);//false
System.out.println(Double.NaN == Double.NaN);//false
System.out.println(Double.compare(Double.NaN, Double.NaN) == 0 ? true : false);//true
ouput nie jest prawidłowe, ponieważ coś, co nie jest liczbą, nie jest po prostu liczbą, i powinny być traktowane na równi z punktu porównania liczby widok. Oczywiste jest również, że 0=-0
.
Zobaczmy co Float.compare
robi:
public static int compare(float f1, float f2) {
if (f1 < f2)
return -1; // Neither val is NaN, thisVal is smaller
if (f1 > f2)
return 1; // Neither val is NaN, thisVal is larger
int thisBits = Float.floatToIntBits(f1);
int anotherBits = Float.floatToIntBits(f2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
Float.floatToIntBits
:
Zwraca reprezentację podanej wartości zmiennoprzecinkowej według zmiennoprzecinkowych IEEE 754 "single Format" układ nieco . Bit 31 (bit wybrany przez maskę 0x80000000) reprezentuje znak liczby zmiennoprzecinkowej. Bity 30-23 (bity wybrane przez maskę 0x7f800000) reprezentują wykładnik. Bity 22-0 (bity wybrane przez maskę 0x007fffff) reprezentują wartość istotną (czasami zwaną mantysą) liczby zmiennoprzecinkowej.
Jeśli argumentem jest nieskończoność dodatnia, wynikiem jest 0x7f800000.
Jeśli argumentem jest ujemna nieskończoność, wynikiem jest 0xff800000.
Jeśli argumentem jest NaN, wynikiem jest 0x7fc00000.
We wszystkich przypadkach wynik jest liczbą całkowitą, przy podawaniu w sposób intBitsToFloat (int) wytworzy wartość zmiennoprzecinkową samo jako argument floatToIntBits (lecz wszystkie wartości NaN są w postaci pojedynczej "kanoniczna" wartość NaN).
Z JLS 15.20.1. Numerical Comparison Operators <, <=, >, and >=
Wynik porównania zmiennoprzecinkowej, jak określono w specyfikacji standardu IEEE 754, jest
Jeżeli jedna argumentu jest liczbą, a następnie wynik jest fałszywy.
Wszystkie wartości inne niż NaN są uporządkowane, z ujemną nieskończonością mniejszą niż wszystkie wartości skończone i dodatnią nieskończonością większą niż wszystkie wartości skończone.
Pozytywne zero i ujemne zero są uważane za równe. Na przykład -0.0 < 0.0 jest fałszywe, ale -0.0 < = 0.0 jest prawdziwe.
Należy jednak zauważyć, że metody Math.min i Math.max traktują ujemne zero jako bezwzględnie mniejsze niż dodatnie zero.
ścisłego porównań gdzie operandy są pozytywne i negatywne zerowy zerowy wynik będzie źle.
Z JLS 15.21.1. Numerical Equality Operators == and !=:
Wynik porównania zmiennoprzecinkowej, jak określono w specyfikacji standardu IEEE 754, jest badanie równość
zmiennoprzecinkowych są wykonywane zgodnie z zasady standardu IEEE 754:
Jeśli któryś argument jest NaN, wówczas wynik == jest fałszywy, ale wynik = prawda!. Rzeczywiście, test x! = X jest prawdziwy wtedy i tylko wtedy, gdy wartość x wynosi NaN. Metody Float.isNaN i Double.isNaN mogą być również użyte do sprawdzenia, czy wartość jest NaN.
Pozytywne zero i ujemne zero są uważane za równe. Na przykład -0.0 == 0.0 jest prawdziwe.
W przeciwnym razie dwie różne wartości zmiennoprzecinkowe są uważane za nierówne przez operatorów równości. W szczególności istnieje jedna wartość reprezentująca pozytywną nieskończoność i jedna wartość reprezentująca ujemną nieskończoność; każdy porównuje się tylko z samym sobą, a każdy porównuje nierówność ze wszystkimi innymi wartościami.
Dla porównania równości gdzie oba operandy są NaN wynik będzie źle.
Od total ordering (=
, <
, >
,<=
, >=
) jest używany przez wiele ważnych algorytmów (patrz all the classes that implement the Comparable interface) lepiej jest użyć metody porównania, ponieważ da to bardziej spójne zachowanie.
Konsekwencją total ordering in the context of the IEEE-754 standard jest różnica między dodatnim i ujemnym zerem.
Na przykład, jeśli używasz operatora równości zamiast metody porównywania i posiadasz pewien zbiór wartości, a twoja logika kodu podejmuje pewne decyzje w oparciu o kolejność elementów i jakoś zaczynasz otrzymywać nadwyżkę wartości NaN będą one traktowane jako różne wartości zamiast tych samych wartości.
Prawdopodobnie spowoduje to błąd w zachowaniu programu proporcjonalny do ilości/szybkości wartości NaN. A jeśli masz dużo dodatnich i ujemnych zer, to tylko jedna para wpływa na twoją logikę z błędem.
Float uses Format 32-bitowy IEEE-754 i podwójny uses 64-bitowy format IEEE-754.
Czy NaN jest równe dowolnemu innemu NaN? Czy jest większy niż, mniejszy lub równy jakiejkolwiek innej liczbie? Czy -0,0f jest równe 0,0f? –
http://stackoverflow.com/a/9341669/1276341 – MrLore
To zależy od tego, co chcesz zrobić. IIRC (nie trzymaj mnie tego) 'NaN == NaN' jest fałszywe, np. Ale oficjalna specyfikacja "porównania" nie daje wiele informacji o tym, jak obsługiwane są przypadki "dziwne". Ważniejsze jest, aby pamiętać, aby nigdy nie porównywać "równości" w ogóle, z wyjątkiem szczególnych przypadków, gdy wiesz, co robisz. –