2010-03-04 10 views
24

So che non possiamo confrontare 2 valori in virgola mobile usando ==. Possiamo solo confrontare che si trovano entro un intervallo l'uno dall'altro. SoÈ possibile confrontare esattamente i valori in virgola mobile a zero?

if(val == 0.512) 

è sbagliato a causa di errori insiti in calcoli in virgola mobile e la conversione in binario e dovrebbe essere

if (val in (0.512-epsilon, 0.512+epsilon)) 

Ma è 0 speciale? Possiamo confrontare i float esattamente a 0? O anche quello non è corretto? In particolare nel contesto di C# e Java?

double val = 0; 
val = getVal(); 
if(val == 0) 
+1

pedanteria matematica: è epsilon, non ephsilon. bella domanda, però. – Carl

+7

Ovviamente è possibile confrontare due valori in virgola mobile usando l'uguaglianza esatta. Per determinati scopi limitati, non è ciò che si vuole fare, ma dire che "non si può" farlo è una sciocchezza, pura e semplice, e impedisce agli sviluppatori di apprendere la semantica reale di virgola mobile. –

+1

@Carl: Grazie per la pedanteria greca! ha modificato il post Sono così abituato a scrivere (U + 0395) ε, non sapevo esattamente l'ortografia! – Fakrudeen

risposta

17

Anche se 0 ha una rappresentazione esatta, non è possibile fare affidamento sul risultato di un calcolo utilizzando i valori float esattamente come 0. Come notato, ciò è dovuto al calcolo in virgola mobile e ai problemi di conversione.

Quindi, dovresti testare per 0 contro il tuo epsilon tolleranza.

+0

Praticamente tutte le risposte mi hanno consigliato contro l'involucro speciale 0. Grazie ! Accettare il primo [in ordine predefinito]. – Fakrudeen

+2

@Fakrudeen: ordine predefinito s per punteggio prima, quindi casuale. –

2

Vorrei ancora seguire l'idioma di tolleranza e non confrontare a zero esattamente.

12

È possibile confrontare a zero se è stato assegnato lo zero variabile. Se ottieni zero da es. una sottrazione puoi ancora ottenere un numero molto piccolo vicino allo zero. ad es .: 0.1-0.1 può valere qualcosa come 1e-9.

0

Non penso che sia possibile in generale - il calcolo che si verifica in getVal() potrebbe logicamente risultare in zero ma che non significa che restituirà zero. Se esplicitamente restituisci uno zero per indicare alcune condizioni, il confronto dovrebbe sempre funzionare ma non penso che sarebbe la migliore pratica. Modificherei la funzione per restituire un codice di stato e passare il valore da modificare byref.

3

Poiché zero ha una rappresentazione esatta, è possibile che un valore confronti == a zero. Se la variabile che stai testando è stata impostata da un compito, o da un valore digitato (come getVal nel tuo esempio?), Potrebbe facilmente essere zero. Ma se era il risultato di un calcolo, le probabilità che fosse esattamente zero sono molto piccole. Ciò è peggiorato perché le frazioni decimali ordinarie come 0.2 non hanno una rappresentazione esatta in virgola mobile. Ecco perché è meglio usare epsilon.

13

Utilizzare la tolleranza /ephsilon.

ho solo valutato le seguenti in Java, che si traduce matematicamente a Zero:

1.0/5.0 + 1.0/5.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0 

e in realtà ottenuto

2.7755575615628914E-17 
+5

+1 per fornire un esempio reale. –

4

Per confronto con err tutto quello che dovete è.

// compare a and b with an ERR error. 
if (Math.abs(a - b) <= ERR) 

da confrontare con 0

// compare a and 0 with an ERR error. 
if (Math.abs(a) <= ERR) 
+0

Che cos'è 'ERR'? – Jess

+1

@Jess Il tuo errore accettabile, ad esempio .static double double ERR = 1e-6' –

+1

Oh, pensavo fosse una specie di acronimo. Forse rinominare in ErrorTolerance? O ZeroTolerance sarebbe divertente: D! – Jess

0

In qualsiasi situazione non banale, si dovrebbe davvero utilizzare solo l'approccio di tolleranza. Come notato, il confronto con lo zero è accurato solo quando lo hai effettivamente assegnato a zero.

Senza ripetere ciò che altri hanno detto, voglio solo sottolineare il fatto che l'utilizzo dell'approccio di tolleranza è più prova futura. Quello che una volta pensate è un compito semplice può comportare l'aritmetica reale più tardi. L'uso di un confronto nudo rende dolorosamente oscuro il debug in un secondo momento.

Problemi correlati