2009-07-17 18 views
77

Qualcuno può spiegarmi questo? In C# Double.NaN non è uguale a Double.NaNPerché double.NaN non è uguale a se stesso?

bool huh = double.NaN == double.NaN; // huh = false 
bool huh2 = double.NaN >= 0; // huh2 = false 
bool huh3 = double.NaN <= 0; // huh3 = false 

Cosa costante posso paragonare a una Double.NaN e ottenere vero?

+11

Solo per spiegare il tuo huh: NaN è uguale a niente, nemmeno a se stessa. Questo è per definizione. http://en.wikipedia.org/wiki/NaN – Falaina

+2

Quello che penso sia sfortunato è che il contesto è perso. Se avessimo due doppi, ad entrambi è stato assegnato un valore di NaN per rappresentare il valore reale 1/0. Dovrebbero essere uguali, ma dal momento che il contesto è stato perso, sono considerati non uguali –

+0

Hai ragione, dovrebbe essere implementata una linea aggiuntiva di codice per quel particolare caso. – Carlo

risposta

127

Se siete curiosi, questo è ciò che appare come Double.IsNaN:

public static bool IsNaN(double d) 
{ 
    return (d != d); 
} 

Funky, eh?

+4

Molto originale! Anche molto intelligente quando ci pensi. –

+0

Interessante. Non ne ero consapevole. Ha senso, una volta che lo vedi però, a causa della definizione di NaN ... – Noldorin

+10

Che strano è tutto ok. Ma poi di nuovo, così è la dichiarazione di NaN: 'public const double NaN = (double) 1.0/(double) 0.0;' –

44

Utilizzare .

15
bool isNaN = Double.IsNaN(yourNumber) 
6

C'è una funzione specializzata per questo:

double.IsNan(huh); 
5

Utilizzare il metodo "Double.IsNaN (valore)" per verificare questa condizione.

7

Utilizzare Double.IsNan() per verificare l'uguaglianza qui. Il motivo è che NaN non è un numero.

9

Il comportamento è di proposito. Il motivo per cui NaN rappresenta qualcosa che non è un numero e quindi è una specie di catch-all per molte cose.

Il modo corretto per confrontare qualcosa con NaN è utilizzare la funzione IsNaN.

3

In realtà, è già trovato il modo per verificare se un numero a virgola mobile IEEE-754 è NaN: è l'unico valore in virgola mobile (o intervallo di valori, perché ci sono diversi NaNs) che restituisce False rispetto a stesso, ovvero:

bool isNaN(double v) { 
    return v != v; 
} 

Sotto il cofano, il metodo Double.IsNaN potrebbe effettivamente fare la stessa cosa. Dovresti comunque usarlo, perché il comportamento è abbastanza sorprendente per chiunque non conosca lo standard FP.

2

L'unica cosa che sappiamo di NaN è che è "Not a Number". Ciò non significa che abbia un valore associabile al suo stato. Per esempio:

∞ + (- ∞) = NaN

0/0 = NaN

(∞ + (- ∞)) <> (0/0)

Ecco qualche C# per dimostrare

var infinity = 100d/0; 
var negInfinity = -100d/0; 

var notANumber = infinity + negInfinity; 
Console.WriteLine("Negative Infinity plus Infinity is NaN: {0}", double.IsNaN(notANumber)); 

var notANumber2 = 0d/0d; 
Console.WriteLine("Zero divided by Zero is NaN: {0}", double.IsNaN(notANumber2)); 

Console.WriteLine("These two are not equal: {0}", notANumber == notANumber2); 
+0

100/0 non è NaN, è Infinito! http://docs.sun.com/source/806-3568/ncg_goldberg.html#918 –

+0

Hai ragione. Sto rivedendo. –

2

Il motivo di Double.NaN != Double.NaN è simple:

Ti aspetti che lo 0/0 sia lo stesso di Math.Sqrt(-3)? E lo stesso di Math.Sqrt(-7)?

C'è un errore in C# a mio avviso, dove Equals() non è sovrascritto per NaN.

Assert.IsTrue(Double.NaN != Double.NaN); 
Assert.IsTrue(Double.NaN.Equals(Double.NaN)); 

Contemporaneamente

Assert.IsTrue(Double.PositiveInfinity == Double.NegativeInfinity); 
Assert.IsTrue(Double.PositiveInfinity.Equals(Double.PositiveInfinity)); 
// same for Double.NegativeInfinity and Single 

Usa funzioni statiche per Double e Single, ad esempio

Double.IsNaN(value) && Double.IsInfinity(value); 

o più specifiche:

Double.IsPositiveInfinity(value); 
Double.IsNegativeInfinity(value); 
2

l'operatore di uguaglianza considera due valori NaN di essere diverso da un altro. In generale, non è possibile utilizzare Double operator per confrontare Double.NaN con altri valori Double, sebbene i metodi di confronto (come uguale a e CompareTo) possano. vedi sotto esempi

referenziati da msdn

class Program 
{ 
    static void Main(string[] args) 
    { 
     Double i = Double.NaN; 
     while (!i.Equals(i)) //this would be result in false 
     //while(i != i) // this would result in true. 
     { 
      Console.WriteLine("Hello"); 
     } 
    } 
} 

here è .net violino per lo stesso.

Problemi correlati