2010-09-13 15 views
6

Jeśli porównać dwie liczby zmiennoprzecinkowe, istnieją przypadki, w których a>=b nie jest równoznaczne z b<=a i !(a<b) lub gdy a==b nie jest równoznaczne z b==a i !(a!=b)?Czy są jakieś "anomalie" porównania zmiennoprzecinkowe?

Innymi słowy: czy porównania zawsze są "symetryczne", że mogę uzyskać taki sam wynik w porównaniu przez zamianę operandów i odzwierciedlenie operatora? Czy są one zawsze "negowalne", tak że negowanie operatora (na przykład > do <=) jest równoważne zastosowaniu logicznego NOT (!) do wyniku?

+0

Dołączyłem akapit drugi, aby wyjaśnić moje pytanie. Zgodnie z przyjętą odpowiedzią, wydaje się, że są one "symetryczne", ale nie "negowalne" z powodu NaN. – mwfearnley

Odpowiedz

7

Zakładając, IEEE 754 zmiennoprzecinkową:

  • a >= b zawsze równoważne b <= a *
  • a >= b odpowiada !(a < b), chyba że jeden lub oba a lub b NaN..
  • a == b zawsze jest równoznaczne z b == a. *
  • a == b jest równoważna !(a != b), chyba że jeden lub oba a lub b jest NaN.

Bardziej ogólnie: trichotomia nie zawiera liczb zmiennoprzecinkowych. Zamiast tego, związanych nieruchomość posiada [IEEE-754 (1985) §5.7]: mniejszy, równy, większy niż i nieuporządkowana: możliwe są

Cztery wzajemnie wykluczające się relacje. Ostatni przypadek powstaje, gdy przynajmniej jeden operand jest NaN. Każdy NaN powinien porównywać nieuporządkowane ze wszystkim, w tym z samym sobą.

Należy pamiętać, że to nie jest tak naprawdę „anomalia” tyle wskutek rozszerzenia arytmetycznych być zamknięte w taki sposób, że stara się zachować spójność z prawdziwej arytmetyki, jeśli to możliwe.

[*] prawdziwe w abstrakcyjnej arytmetyce IEEE-754. W prawdziwym użyciu niektóre kompilatory mogą spowodować, że zostanie to naruszone w rzadkich przypadkach w wyniku wykonywania obliczeń z większą precyzją (MSVC, patrzę na ciebie). Teraz, większość obliczeń zmiennoprzecinkowych na architekturze Intel odbywa się na SSE zamiast na x87, to mniej niepokoi (i tak zawsze był to błąd z punktu widzenia IEEE-754).

1

Nie, nie dla żadnej praktycznej implementacji zmiennoprzecinkowej: obowiązuje podstawowa symetria i logika logiczna. Jednak equality in floating point numbers jest podchwytliwy na inne sposoby. Istnieje bardzo niewiele przypadków, w których testowanie a==b dla obiektów pływających jest uzasadnione.

3

W Pythonie przynajmniej a>=b nie jest równoznaczne z !(a<b) kiedy jest zaangażowany NaN:

>>> a = float('nan') 
>>> b = 0 
>>> a >= b 
False 
>>> not (a < b) 
True 

Mogę sobie wyobrazić, że jest to również w przypadku większości innych języków.

Inną rzeczą, która może zaskoczyć to, że NaN nawet nie porównać równe sobie:

>>> a == a 
False 
+2

+1: Dowolny system, który używa zmiennoprzecinkowego punktu IEEE będzie miał dziwne zachowanie (lub wyrzuci wyjątki przy tworzeniu takiej błędnej wartości, w końcu wskazuje, gdzie bardzo źle poszło arytmetyczne, na przykład wynik dzielenia 0,0 o 0,0). –

3

zestawu IEEE-754 liczb zmiennoprzecinkowych nie są uporządkowane tak trochę relacyjnej i Boole'a jesteś znany już nie ma. Ta anomalia jest spowodowana przez NaN, który nie ma porządku w odniesieniu do żadnej innej wartości w zbiorze, w tym samej siebie, więc wszystkie operatory relacyjne zwracają fałsz. Dokładnie to pokazuje Mark Byers.

Jeśli wykluczysz NaN, otrzymasz teraz uporządkowany zestaw, a wyrażenia, które podasz, będą zawsze równoważne. Dotyczy to nieskończoności i ujemnego zera.

2

Oprócz kwestii NaN, która jest nieco analogiczna do NULL w SQL i brakujących wartości w SAS i innych pakietach statystycznych, zawsze istnieje problem dokładności arytmetycznej zmiennoprzecinkowej. Wielkości powtarzające się w części ułamkowej (na przykład 1/3) i liczby niewymierne nie mogą być dokładnie odwzorowane. Arytmatyka zmiennoprzecinkowa często obcina wyniki ze względu na skończoną granicę precyzji. Im więcej arithematic zrobić z wartości zmiennoprzecinkowej, tym większy błąd, który wkrada się w

Prawdopodobnie najbardziej użytecznym sposobem porównać zmiennoprzecinkowych byłoby z algorytmu.

  1. Jeżeli którakolwiek wartość jest NaN wszystkie porównania są fałszywe, chyba że wyraźnie sprawdzasz NaN.
  2. Jeśli różnica między dwiema liczbami mieści się w określonym "współczynniku rozmycia", należy uznać je za równe. Współczynnik krycia jest twoją tolerancją dla zakumulowanej niedokładności matematycznej.
  3. Po rozmytym porównywaniu równości, porównaj za mniej niż lub więcej.

Należy zauważyć, że porównanie dla "< =" lub "> =" ma takie samo ryzyko jak przy porównywaniu dla dokładnej równości.