Warum ist double.NaN nicht gleich sich selbst?

82

Kann mir das jemand erklären? In C # ist double.NaN nicht gleich double.NaN

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

Welche Konstante kann ich mit einem double.NaN vergleichen und wahr werden?

Carlo
quelle
12
Nur um Ihre huhs zu erklären: NaN ist gleich nichts, nicht einmal sich selbst. Dies ist per Definition. en.wikipedia.org/wiki/NaN
Falaina
2
Was ich für bedauerlich halte, ist, dass der Kontext verloren geht. Wenn wir zwei Doppel hatten und beiden ein NaN-Wert zugewiesen wurde, um den tatsächlichen Wert 1/0 darzustellen. Sie sollten gleich sein, aber da der Kontext verloren geht, werden sie als ungleich behandelt
Michael Meadows
13
mathematisch korrekt. Warum sollte man denken, ein Nan wäre gleich einem anderen? sqrt (-1)! = 1/0
Gordon Gustafson
2
Es ist genau wie NULLin SQL
Shashwat
2
@MichaelMeadows 1/0 ist Inf, nicht NaN.
Jim Balter

Antworten:

133

Wenn Sie neugierig sind, Double.IsNaNsieht das so aus:

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

Funky, was?

Erich Mirabal
quelle
11
Das ist schon komisch. Aber auch die Erklärung von NaN:public const double NaN = (double) 1.0 / (double) 0.0;
Fredrik Mörk
5
@Fredik, @Erich: Division durch Null ergibt inf (oder + inf, -inf basierend auf den Operanden), 0/0 (unter anderem) ergibt eine NaN. Es gibt eine schöne Tabelle mit speziellen Operationen / Ergebnissen unter steve.hollasch.net/cgindex/coding/ieeefloat.html
Torsten Marek
5
Um die Verwirrung zu vergrößern, gibt object.Equals (double.NaN, double.NaN) true zurück
Román
2
@ JimBalter Sie haben Recht, dass mein Kommentar falsch war: Die Referenzquelle sagt tatsächlich public const double NaN = (double)0.0 / (double)0.0; Link zur Referenzquelle . Vielen Dank für den Hinweis. Noch ein Hinweis: Unrecht und Lügen sind zwei völlig verschiedene Dinge
Fredrik Mörk
1
Ich bin mir nicht sicher, ob dies korrekt war, als Sie es gepostet haben, aber IsNaN ist heute anders definiert .
Joe Amenta
45

Verwenden Sie Double.IsNaN .

Adrian Godong
quelle
16
bool isNaN = Double.IsNaN(yourNumber)
Francis B.
quelle
10

Das Verhalten ist absichtlich. Der Grund dafür, dass NaN etwas ist, das keine Zahl ist und daher für viele Dinge eine Art Allheilmittel ist.

Der richtige Weg, etwas mit NaN zu vergleichen, ist die Verwendung der IsNaN- Funktion.

Mike Dinescu
quelle
7

Verwenden Sie Double.IsNan () , um hier die Gleichheit zu testen. Der Grund ist, dass NaN keine Zahl ist.

Colin Mackay
quelle
6

Hierfür gibt es eine spezielle Funktion:

double.IsNan(huh);
arul
quelle
5

Verwenden Sie die Methode "Double.IsNaN (Wert)", um diese Bedingung zu überprüfen.

David
quelle
3

Tatsächlich haben Sie bereits den Weg gefunden, um zu überprüfen, ob eine IEEE-754-Gleitkommazahl NaN ist : Dies ist der einzige Gleitkommawert (oder Wertebereich, da es mehrere NaNs gibt), der im FalseVergleich zu sich selbst ausgewertet wird , dh:

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

Unter der Haube könnte die Double.IsNaN-Methode tatsächlich dasselbe tun. Sie sollten es trotzdem verwenden, da das Verhalten für jeden, der den FP-Standard nicht kennt, ziemlich überraschend ist.

Torsten Marek
quelle
2

Das einzige, was wir über NaN wissen, ist, dass es "keine Zahl" ist. Das bedeutet nicht, dass es einen Wert hat, der mit seinem Status verknüpft werden kann. Beispielsweise:

∞ + (-∞) = NaN

0/0 = NaN

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

Hier ist ein C # zum Demonstrieren

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);
Michael Meadows
quelle
2

Der Grund dafür Double.NaN != Double.NaNist einfach:

Erwarten Sie 0/0das Gleiche wie Math.Sqrt(-3)? Und das gleiche wie Math.Sqrt(-7)?

Meiner Meinung nach gibt es einen Fehler in C #, der Equals()für NaN nicht überschrieben wird.

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

Gleichzeitig

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

Verwenden Sie statische Funktionen für Doubleund Single, z

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

Oder genauer:

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

Der Gleichheitsoperator betrachtet zwei NaN-Werte als ungleich zueinander. Im Allgemeinen können Double-Operatoren nicht zum Vergleichen von Double.NaN mit anderen Double-Werten verwendet werden, obwohl Vergleichsmethoden (wie Equals und CompareTo ) dies können. siehe unten Beispiele

Referenziert von 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");
        }
    }
}

Hier ist .net Geige für das gleiche.

Jenish Rabadiya
quelle