2010-09-13 14 views
6

Se si confrontano due numeri in virgola mobile, ci sono casi in cui a>=b non è equivalente a b<=a e !(a<b) o dove a==b non equivale a b==a e !(a!=b)?Esistono "anomalie" di confronto a virgola mobile?

In altre parole: i confronti sono sempre "simmetrici", in modo tale da ottenere lo stesso risultato su un confronto scambiando gli operandi e rispecchiando l'operatore? E sono sempre "negabili", in modo tale che la negazione di un operatore (ad esempio > a <=) equivale a applicare un risultato logico NOT (!) al risultato?

+0

Ho aggiunto un secondo paragrafo per chiarire la mia domanda. Come per la risposta accettata, sembrerebbe che siano "simmetrici" ma non "negabili" a causa dei NaN. – mwfearnley

risposta

7

Supponendo IEEE-754 virgola mobile:

  • a >= b è sempre equivalente a b <= a *
  • a >= b è equivalente a !(a < b), a meno che uno o entrambi a o b è NaN..
  • a == b è sempre equivalente a b == a. *
  • a == b equivale a !(a != b), a meno che uno o entrambi a o b è NaN.

Più in generale: tricotomia non valido per i numeri in virgola mobile. Invece, una proprietà correlate detiene [IEEE-754 (1985) §5.7]:

Quattro relazioni reciprocamente esclusivi sono possibili: minore, uguale, maggiore di, e non ordinata. L'ultimo caso si verifica quando almeno un operando è NaN. Ogni NaN si confronterà non ordinato con tutto, incluso se stesso.

noti che questo non è davvero una "anomalia" tanto come conseguenza di estendere l'aritmetica ad essere chiuso in modo che tenta di mantenere la coerenza con reale aritmetica quando possibile.

[*] vero in astratto aritmetica IEEE-754. Nell'uso reale, alcuni compilatori potrebbero causare la violazione di questo in rari casi come risultato di calcoli con precisione estesa (MSVC, sto osservando te). Ora che la maggior parte del calcolo a virgola mobile sull'architettura Intel viene eseguita su SSE anziché su x87, questo è meno preoccupante (ed è sempre stato un bug dal punto di vista di IEEE-754, comunque).

1

No, non per qualsiasi implementazione in virgola mobile: si applicano la simmetria di base e la logica booleana. Tuttavia, equality in floating point numbers è complicato in altri modi. Ci sono pochissimi casi in cui il test a==b per i galleggianti è la cosa giusta da fare.

3

In Python, almeno a>=b non equivale a !(a<b) quando c'è un NaN coinvolto:

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

Immagino che questo è anche il caso della maggior parte delle altre lingue.

Un'altra cosa che potrebbe sorprendere è che NaN non è neanche paragonabile uguale a se stesso:

>>> a == a 
False 
+2

+1: Qualsiasi sistema che utilizza il virgola mobile IEEE avrà questo strano comportamento (o genererà eccezioni a te per produrre un valore errato, dopotutto indica dove l'aritmetica è andata male, come il risultato della divisione di 0.0 di 0,0). –

3

L'insieme di IEEE 754-numeri in virgola mobile non sono ordinati in modo un po 'di algebra relazionale e booleana sei familiare con non tiene più. Questa anomalia è causata da NaN che non ha ordine rispetto a nessun altro valore dell'insieme, incluso se stesso, quindi tutti gli operatori relazionali restituiscono false. Questo è esattamente ciò che Mark Byers ha mostrato.

Se escludi NaN, ora hai un set ordinato e le espressioni che hai fornito saranno sempre equivalenti. Questo include gli infiniti e lo zero negativo.

2

A parte il problema NaN, che è in qualche modo analogo a NULL in SQL e ai valori mancanti in SAS e altri pacchetti statistici, c'è sempre il problema della precisione aritmetica in virgola mobile. I valori ripetuti nella parte frazionaria (1/3, ad esempio) e i numeri irrazionali non possono essere rappresentati con precisione. L'aritmetica a virgola mobile spesso tronca i risultati a causa del limite finito di precisione. Quanto più arithematic si fa con un valore in virgola mobile, il più grande l'errore che si insinua nel

Probabilmente il modo più utile per confrontare valori in virgola mobile sarebbe stato con un algoritmo:.

  1. Se uno dei due valori è NaN , tutti i confronti sono falsi, a meno che non si stia verificando esplicitamente NaN.
  2. Se la differenza tra due numeri è all'interno di un determinato "fattore di fuzz", considerarli uguali. Il fattore fuzz è la tua tolleranza per l'imprecisione matematica accumulata.
  3. Dopo il confronto di uguaglianza fuzzy, quindi confrontare per minore o maggiore di.

Si noti che il confronto per "< =" o "> =" ha lo stesso rischio del confronto per l'uguaglianza precisa.

Problemi correlati