Was ist der Grund für alle Vergleiche false zurückgeben, für IEEE754 NaN-Werte?
Warum Vergleiche von NaN-Werte Verhalten sich anders als alle anderen Werte?
Das heißt, alle Vergleiche mit den Operatoren ==, <=, >=, <, > wo einer oder beide Werte NaN false zurückgibt, im Gegensatz zu dem Verhalten aller anderen Werte.
Ich nehme an, dies vereinfacht die numerischen Berechnungen in gewisser Weise, aber ich konnte nicht finden eine explizit angegebene Grund, das nicht auch in der Vorlesung Notizen auf den Status von IEEE 754 von Kahan, der diskutiert, andere design-Entscheidungen im detail.
Dieses abweichende Verhalten verursacht Probleme, wenn dabei die einfache Verarbeitung der Daten. Zum Beispiel beim Sortieren einer Liste mit Datensätzen, die w.r.t. einige real-valued-Feld in ein C-Programm muss ich zusätzlichen code schreiben zu behandeln NaN als maximales element, da sonst die sort-Algorithmus könnte verwirrt werden.
Edit:
Die Antworten, die bisher alle argumentieren, dass es sinnlos ist zu vergleichen NaNs.
Ich Zustimmen, aber das bedeutet nicht, dass die Antwort richtig ist, ist falsch,
eher würde es sich um einen Nicht-Boolean (NaB), die glücklicherweise aber nicht vorhanden ist.
So dass die Wahl der Rückgabe von true oder false für Vergleiche ist in meinen Augen willkürlich,
und für Allgemeine Datenverarbeitung wäre es von Vorteil, wenn es gehorchte den gewöhnlichen Gesetzen
(Reflexivität von ==, Dreiteilung der <, ==, >),
damit Datenstrukturen, die darauf angewiesen sind, diese Gesetze zu verwechseln.
Daher bitte ich um einige konkrete Vorteil, diese Gesetze zu brechen, nicht nur philosophische Argumentation.
Edit 2:
Ich glaube, ich verstehe jetzt warum NaN maximale wäre eine schlechte Idee, es würde mess up die Berechnung der oberen Grenzen.
NaN != NaN könnte wünschenswert sein, um zu vermeiden, erkennen von Konvergenz in einer Schleife wie
while (x != oldX) {
oldX = x;
x = better_approximation(x);
}
was allerdings sollte besser geschrieben werden, durch vergleichen der absoluten Differenz mit einem kleinen limit.
Also IMHO ist dies ein relativ schwaches argument für das brechen der Reflexivität in NaN.
while (fabs(x - oldX) > threshold)
, verlassen Sie die Schleife, wenn Konvergenz Eintritt oder ein NaN tritt in die Berechnung. Nachweis von NaN-und entsprechende Abhilfe würde dann geschehen außerhalb der Schleife.Wenn NaN wurden die minimales element von der Ordnung, die while-Schleife würde immer noch funktionieren.
Food for thought: grouper.ieee.org/groups/1788/email/pdfmPSi1DgZZf.pdf - Seite 10
InformationsquelleAutor starblue | 2009-10-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
War ich Mitglied in der IEEE-754-Ausschuss, werde ich versuchen zu klären, die Dinge ein wenig.
First off, floating-point-zahlen sind nicht real-zahlen und Gleitkomma-Arithmetik erfüllt nicht die Axiome der real-Arithmetik. Dreiteilung ist nicht die einzige Eigenschaft, der real-Arithmetik gilt das nicht für Schwimmer, noch nicht einmal das wichtigste. Zum Beispiel:
Ich gehen konnte. Es ist nicht möglich, an eine Feste Größe arithmetischen Typ, die erfüllt alle der Eigenschaften von real-Arithmetik, die wir kennen und lieben. Die 754 Ausschuss hat zu entscheiden, auf biegen oder brechen einige von Ihnen. Diese wird geleitet durch einige sehr einfache Prinzipien:
Bezug auf deinen Kommentar "das bedeutet nicht, dass die korrekte Antwort ist falsch", das ist falsch. Das Prädikat
(y < x)
fragt, oby
ist weniger alsx
. Wenny
ist "NaN", dann ist es nicht weniger als jede floating-point-Wertx
, die Antwort ist also unbedingt falsch.Ich erwähnt, dass die Dreiteilung nicht für floating-point-Werte. Allerdings gibt es eine ähnliche Eigenschaft halten. Klausel 5.11, Absatz 2 des 754-2008 standard:
Soweit zusätzlichen code schreiben zu behandeln NaNs geht, ist es meist möglich (wenn auch nicht immer einfach) strukturieren Sie Ihren code in einer Weise, dass NaNs Herbst richtig durch, aber das ist nicht immer der Fall. Wenn es nicht, einige zusätzliche code kann notwendig sein, aber das ist ein kleiner Preis zu zahlen, für die Bequemlichkeit, die algebraische Schließung gebracht, um floating-point-Arithmetik.
Nachtrag:
Viele Kommentatoren haben argumentiert, dass es wäre nützlicher zu bewahren Reflexivität der Gleichheit und der Dreiteilung der Begründung, dass die Annahme NaN != NaN scheint nicht zu bewahren bekannte axiom. Ich gestehe zu, dass einige Sympathie für diesen Standpunkt, so dass ich dachte, ich wäre zu überdenken, diese zu beantworten und bieten ein bisschen mehr Kontext.
Mein Verständnis aus einem Gespräch mit Kahan ist, dass NaN != NaN stammt aus zwei pragmatische überlegungen:
Dass
x == y
sollte äquivalent zux - y == 0
wenn möglich (abgesehen davon, dass ein Satz von real-Arithmetik, das macht die hardware-Implementierung von Vergleich mehr Speicherplatz-effizienter, und das war von größter Bedeutung, zu der Zeit wurde der standard entwickelt — beachten Sie jedoch, dass diese verletzt wird, der für x = y = unendlich, so dass es nicht einen großen Grund, auf Ihre eigenen; es vernünftigerweise wurde gebogen, um(x - y == 0) or (x and y are both NaN)
).Wichtiger ist, es war keine
isnan( )
Prädikat an der Zeit, dass NaN formalisiert wurde in der 8087 Arithmetik; es war notwendig, den Programmierer eine bequeme und effiziente Mittel zum erkennen von NaN-Werte nicht davon abhängen, Programmiersprachen bieten so etwas wieisnan( )
könnte viele Jahre dauern. Ich zitiere Kahan eigenen schreiben über das Thema:Beachten Sie, dass dies ist auch die Logik, die Regeln der Rückkehr so etwas wie eine "not-A-Boolean". Vielleicht ist dieser Pragmatismus war fehl am Platze, und der standard haben sollte, erforderlich
isnan( )
, aber das hätte NaN fast unmöglich zu verwenden, effizient und bequem für mehrere Jahre, während die Welt wartete Programmiersprache Annahme. Ich bin nicht davon überzeugt, das wäre ein angemessener Kompromiss.Um ehrlich zu sein: das Ergebnis NaN == NaN ist nicht zu ändern jetzt. Besser lernen mit ihm zu Leben, als sich zu beschweren über das internet. Wenn Sie möchten, um zu argumentieren, dass eine Bestellung mit Bezug geeignet für Behälter sollten auch vorhanden ist, würde ich empfehlen, zu befürworten, dass Ihre Lieblings-Programmiersprache implementieren, die
totalOrder
Prädikat standardisiert in IEEE-754 (2008). Die Tatsache, dass es nicht bereits spricht für die Gültigkeit von Kahan ' s Anliegen motiviert, den aktuellen Stand der Dinge.Vereinbart ist; der nonreflexivity von NaNs geschaffen hat, kein Ende der Schmerzen für Sprachen wie Python, mit den Gleichstellungs-basierte containment-Semantik. Sie wirklich nicht wollen, dass die Gleichberechtigung nicht zu sein eine aquivalenzrelation, wenn Sie versuchen zu bauen Container oben drauf. Und mit zwei getrennten Vorstellungen von Gleichheit ist nicht viel von einem freundlichen option entweder, für eine Sprache, die eigentlich leicht zu erlernen. Das Ergebnis (im Fall von Python) ist eine unangenehm fragilen Kompromiss zwischen der Einhaltung IEEE 754-und-nicht-zu-kaputt-containment-Semantik. Zum Glück ist es selten zu legen NaNs in die Container.
Einige schöne Beobachtungen hier: bertrandmeyer.com/2010/02/06/...
Was würdest (0/0) == (+INF) + (-INF) mehr unsinnig als
1f/3f == 10000001f/30000002f
? Wenn Gleitkomma-Werte werden als äquivalenz-Klassen, danna=b
bedeutet nicht, dass "Die Berechnungen, die ergabena
undb
, wenn man mit unendlicher Genauigkeit, würde die Ausbeute identische Ergebnisse", sondern eher "Was ist bekannt übera
übereinstimmungen mit dem, was ist bekannt überb
". Ich bin gespannt, ob Sie kennen, die Beispiele des Codes, wo mit "Nan != NaN" macht die Dinge einfacher, als Sie würden anders sein?Es ist wahr, dass die floating-point Mathematik nicht als Gruppe Verhalten, viel weniger ein ring oder ein Feld, aber das bedeutet nicht, dass floating-point-zahlen sollten nicht definieren eine äquivalenz-relation. Ich verstehe, dass die IEEE empfohlen, eine Reihe von transitiven relationalen Operatoren in 2007, aber finde mich verwundert, warum ein problem, das sollte deutlich geworden ist das erste mal, dass jemand versuchte, Sie zu Sortieren einer Liste von zahlen, enthält eine NaN benötigt immer noch einen kniffligen multi-step workaround. Sortierung code ist oft eine der mehr performance-sensitive Anwendungen für floating-point-Vergleiche...
InformationsquelleAutor Stephen Canon
NaN kann gedacht werden als ein undefinierter Zustand/Zahl. ähnlich wie das Konzept von 0/0 als undefined oder sqrt(-3) (in die real-Zahl-system, wo die floating-point -) Leben.
NaN dient als eine Art Platzhalter für diese undefinierten Zustand. Mathematisch das sprechen, das undefiniert ist nicht gleich undefined. Weder können Sie sagen, einen nicht definierten Wert, der größer oder kleiner als ein anderes, nicht definierten Wert. Daher sind alle Vergleiche false zurück.
Dieses Verhalten ist auch vorteilhaft in den Fällen, in denen Sie vergleichen sqrt(-3) , sqrt(-2). Sie würden beide return NaN, aber Sie sind nicht äquivalent, obwohl Sie den gleichen Wert zurückgeben. Also mit Gleichheit immer false zurückgeben, wenn der Umgang mit NaN ist das gewünschte Verhalten.
sqrt(a) = sqrt(b) <=> a = b
Was sollte das Ergebnis von sqrt(1.00000000000000022)==sqrt(1.0)? Wie über (1E308+1E308-1E308-1E308-1E308)==(1E308+1E308)? Auch nur fünf der sechs Vergleiche den Wert false zurück. Die
!=
- operator gibt true zurück. MitNaN==NaN
undNaN!=NaN
beide false zurückgeben würde es erlauben, code, vergleicht x und y zu wählen, was passieren soll, wenn beide Operanden NaN, indem Sie entweder==
oder!=
.InformationsquelleAutor Chris
Werfen noch eine andere Analogie. Wenn ich die hand, die Sie zwei Kästen, und Ihnen sagen, dass keines von Ihnen enthält ein Apfel, würde Sie mir sagen, dass die Boxen enthalten die gleiche Sache?
NaN enthält keine Informationen über das, was etwas ist, nur was es nicht ist. Daher sind diese Elemente können nie definitiv gesagt werden, gleich ist.
Die Boxen die Sie gegeben sind, sind NICHT bekannt, leer zu sein.
Würden Sie mir sagen, die Boxen enthalten nicht die gleiche Sache? Ich kann verstehen, dass die Begründung für
(NaN==Nan)==false
. Was ich nicht verstehe ist die Begründung für(Nan!=Nan)==true
.Ich nehme an, NaN != NaN ist wahr, denn x != y ist definiert als !(x == y). Zugegeben, ich weiß nicht, ob die IEEE-Spezifikation definiert es so.
Aber in dieser Analogie, wenn du mir eine box, die sagte, dass Sie nicht enthalten äpfel, fragte mich dann, ob es gleich an sich selbst, erwarten Sie von mir, Nein zu sagen? Denn das ist es, was ich zu sagen hätte nach IEEE.
InformationsquelleAutor Jack Ryan
Aus dem wikipedia-Artikel über NaN, die folgenden Praktiken verursachen können NaNs:
Da es keine Möglichkeit gibt zu wissen, welche dieser Vorgänge erstellt, die NaN, es gibt keine Möglichkeit, Sie zu vergleichen, macht Sinn.
InformationsquelleAutor Stefan Rusek
Ich weiß nicht, die design-Grundlagen, aber hier ist ein Auszug aus dem IEEE 754-1985-standard:
"Es muss möglich sein zu vergleichen, floating-point-zahlen in alle unterstützten Formate, auch wenn die Operanden-Formate unterscheiden. Vergleiche sind genaue und nie überlauf noch Unterlauf. Vier sich gegenseitig ausschließende Beziehungen sind möglich: weniger als, gleich, größer als, und ungeordnet. Der Letzte Fall entsteht, wenn mindestens einer der Operanden NaN ist. Jedes NaN vergleichen, ungeordneten, mit alles, einschließlich sich selbst."
InformationsquelleAutor Rick Regan
Es sieht nur eigenartig, weil die meisten Programmierumgebungen, die es ermöglichen, NaNs nicht erlauben auch die 3-wertige Logik. Wenn Sie werfen 3-wertige Logik in den mix, es wird konsequent:
Selbst .NET bietet keine
bool? operator==(double v1, double v2)
operator, so sind Sie noch fest mit dem dummen(NaN == NaN) = false
Ergebnis.InformationsquelleAutor Christian Hayter
Ich vermute, dass NaN (not A Number) bedeutet genau das: Dieses ist keine Zahl und somit der Vergleich nicht wirklich sinnvoll.
Es ist ein bisschen wie Arithmetik in SQL mit
null
Operanden: Sie alle führennull
.Vergleiche für floating-point-zahlen vergleichen die numerischen Werte. Daher können Sie nicht verwendet werden für nicht numerische Werte. NaN kann deshalb nicht verglichen werden, die in einem numerischen Sinn.
ja, vergleicht einen string in einen string macht Sinn. Aber vergleicht man einen string um, sagen wir, äpfel, macht nicht viel Sinn. Da äpfel und Birnen sind nicht zahlen, macht es Sinn, Sie zu vergleichen? Was ist größer?
In SQL, weder "WENN" NULL=NULL DANN FOO;" noch", WENN Null<>Null ist DANN CALL FOO;" [oder wie auch immer die syntax ist], wird ausgeführt
FOO
. Für NaN gleichwertigif (NaN != NaN) foo();
sollte nicht ausführenfoo
, aber es funktioniert.InformationsquelleAutor Daren Thomas
Den über-vereinfachte Antwort ist, dass ein NaN hat keinen numerischen Wert, so gibt es nichts zu vergleichen, nichts anderes.
Könnten Sie die Prüfung und ersetzen Sie Ihre NaN +INF, wenn Sie wollen, dass Sie handeln, wie +INF.
InformationsquelleAutor David R Tribble
Während ich damit einverstanden, dass der Vergleich von NaN mit jede reelle Zahl sein sollte, ungeordnet, ich denke, es ist nur die Ursache für den Vergleich von NaN mit sich selbst. Wie zum Beispiel entdeckt man den Unterschied zwischen signaling NaNs und Stille NaNs? Wenn wir denken, der Signale als eine Reihe boolescher Werte (D. H. eine bit-Vektor) man könnte Fragen, ob die bit-Vektoren sind gleich oder Verschieden und bestellen Sie die Sätze entsprechend. Zum Beispiel, auf der Entzifferung der maximale exponent, wenn die Mantisse wurden nach Links verschoben, so richten Sie die am meisten signifikante bit der Mantisse auf das most significant bit des binären format, ein negativer Wert würde eine ruhige NaN und einer beliebigen positiven Wert wäre ein Signal-NaN. Null der Kurs ist reserviert für die Unendlichkeit und der Vergleich wäre ungeordnet. MSB-Ausrichtung erlauben würde, für einen direkten Vergleich der Signale auch aus den verschiedenen Binär-Formaten. Zwei NaNs mit dem gleichen Satz von Signalen, wären daher äquivalent und die Bedeutung der Geschlechter.
InformationsquelleAutor Patrick Campbell
NaN ist eine implizite neuen Instanz (einer besonderen Art des Laufzeit-Fehlers). Das bedeutet, dass
NaN !== NaN
aus dem gleichen Grund, dassnew Error !== new Error
;Und Bedenken Sie, dass eine solche Selbstverständlichkeit ist auch draußen gesehen Fehler, zum Beispiel im Rahmen von regulären Ausdrücken bedeutet es
/a/!== /a/
das ist nur syntax sugar fürnew RegExp('a') !== new RegExp('a')
x = NaN; x === x
erhalten Siefalse
. Dies unterscheidet sich von Fehler:x = new Error; x === x
die Ihnentrue
!InformationsquelleAutor Ivan Castellanos
Da ist die Mathematik der Bereich, wo die zahlen "einfach nur existieren".
In der informatik müssen Sie initialisieren diese zahlen und halten Ihren Staat nach Ihren Bedürfnissen.
Auf die alten Tage Speicher Initialisierung arbeitete in der Hinsicht kann man sich nie verlassen. Sie konnten es nie lassen Sie sich über diese denken "oh, das wäre initialisiert mit 0xCD die ganze Zeit, mein algo wird auch nicht gebrochen".
So müssen Sie die richtige nicht mischen Lösungsmittel, die klebrig genug zu nicht nicht dass dein Algorithmus immer angesaugt und gebrochen.
Gute algorithmen mit zahlen sind meist mit Beziehungen, und diejenigen, die wenn() Beziehungen weggelassen werden.
Dies ist nur Fett, die in neuen Variablen bei der Bildung, anstelle der Programmierung von random-Hölle von computer-Speicher. Und Ihren Algorithmus, was immer es ist, wird nicht brechen.
Nächsten, wenn Sie noch plötzlich finden Sie heraus, dass Ihr Algorithmus ist die Herstellung von NaNs, es ist möglich, reinigen Sie es aus, suchen in jedem Zweig ein zu einer Zeit. Wieder, "immer falsch" - Regel hilft eine Menge in diesem.
InformationsquelleAutor sanaris
Für mich, der einfachste Weg es zu erklären ist:
Kann man nicht vergleichen NaN mit etwas anderem (selbst), weil es nicht einen Wert haben. Es kann auch ein beliebiger Wert (außer a number).
InformationsquelleAutor Halil Tevfik
Sehr kurze Antwort:
Da die folgenden:
nan /nan = 1
muss NICHT halten. Ansonsten
inf/inf
wäre 1.(Daher
nan
nicht gleichnan
. Für>
oder<
, wennnan
würde respektieren ordnungsrelation in einer Menge zur Befriedigung der archimedischen Eigenschaft, wir würden wiedernan /nan = 1
an der Grenze ist).inf = inf
undinf / inf = nan
, sonan = nan
wird nicht verhindern, dassnan / nan = nan
.Du meinst
nan / nan = 1
? Eh... Deine Argumentation macht Sinn, wenn inf und nan waren so wie alle anderen zahlen. Es ist nicht der Fall. Der Grund, waruminf/inf
mussnan
(oder unbestimmten form in der Mathematik) und nicht1
ist subtiler als einfache algebraische manipulation (siehe De L ' Hospital-theorem).InformationsquelleAutor SeF