Ich war Mitglied des IEEE-754-Komitees. Ich werde versuchen, die Dinge ein wenig zu klären.
Zunächst einmal sind Gleitkommazahlen keine reellen Zahlen, und Gleitkomma-Arithmetik erfüllt nicht die Axiome der reellen Arithmetik. Die Trichotomie ist nicht die einzige Eigenschaft der realen Arithmetik, die weder für Floats noch für die wichtigste gilt. Beispielsweise:
- Addition ist nicht assoziativ.
- Das Verteilungsgesetz gilt nicht.
- Es gibt Gleitkommazahlen ohne Inversen.
Ich könnte weitermachen Es ist nicht möglich, einen arithmetischen Typ fester Größe anzugeben, der alle Eigenschaften der realen Arithmetik erfüllt , die wir kennen und lieben. Das 754-Komitee muss beschließen, einige von ihnen zu biegen oder zu brechen. Dies wird von einigen ziemlich einfachen Prinzipien geleitet:
- Wenn wir können, passen wir das Verhalten der realen Arithmetik an.
- Wenn wir nicht können, versuchen wir, die Verstöße so vorhersehbar und so einfach wie möglich zu diagnostizieren.
In Bezug auf Ihren Kommentar "Das bedeutet nicht, dass die richtige Antwort falsch ist" ist dies falsch. Das Prädikat (y < x)
fragt, ob y
es kleiner als ist x
. Wenn y
NaN ist, ist es nicht kleiner als ein Gleitkommawert x
, daher ist die Antwort notwendigerweise falsch.
Ich erwähnte, dass die Trichotomie nicht für Gleitkommawerte gilt. Es gibt jedoch eine ähnliche Eigenschaft, die gilt. Abschnitt 5.11, Absatz 2 der Norm 754-2008:
Es sind vier sich gegenseitig ausschließende Beziehungen möglich: kleiner als, gleich, größer als und ungeordnet. Der letzte Fall tritt auf, wenn mindestens ein Operand NaN ist. Jedes NaN soll ungeordnet mit allem vergleichen, auch mit sich selbst.
Wenn Sie zusätzlichen Code für den Umgang mit NaNs schreiben, ist es normalerweise möglich (wenn auch nicht immer einfach), Ihren Code so zu strukturieren, dass NaNs ordnungsgemäß durchfallen. Dies ist jedoch nicht immer der Fall. Wenn dies nicht der Fall ist, ist möglicherweise ein zusätzlicher Code erforderlich, aber dies ist ein geringer Preis für die Bequemlichkeit, die das algebraische Schließen der Gleitkomma-Arithmetik gebracht hat.
Nachtrag: Viele Kommentatoren haben argumentiert, dass es sinnvoller wäre, die Reflexivität von Gleichheit und Trichotomie zu bewahren, da die Übernahme von NaN! = NaN kein bekanntes Axiom zu bewahren scheint. Ich gebe zu, Sympathie für diesen Standpunkt zu haben, deshalb dachte ich, ich würde diese Antwort noch einmal überdenken und ein bisschen mehr Kontext bieten.
Mein Verständnis aus dem Gespräch mit Kahan ist, dass NaN! = NaN aus zwei pragmatischen Überlegungen hervorgegangen ist:
Das x == y
sollte nicht höher sein , x - y == 0
wenn möglich (über einen Satz von realer Arithmetik zu sein, das macht Hardware - Implementierung des Vergleiches platzsparender, die zu der Zeit von größter Bedeutung war der Standard entwickelt wurde - jedoch zu beachten, dass dies für x verletzt = y = unendlich, es ist also kein guter Grund für sich; es hätte vernünftigerweise dazu neigen können (x - y == 0) or (x and y are both NaN)
).
Noch wichtiger ist, dass es isnan( )
zum Zeitpunkt der Formalisierung von NaN in der 8087-Arithmetik kein Prädikat gab . Es war notwendig, Programmierern ein bequemes und effizientes Mittel zur Erkennung von NaN-Werten zur Verfügung zu stellen, die nicht von Programmiersprachen abhingen, die so etwas wie isnan( )
viele Jahre dauern konnten. Ich zitiere Kahans eigenes Schreiben zu diesem Thema:
Wenn es keine Möglichkeit gäbe, NaNs loszuwerden, wären sie genauso nutzlos wie Indefinites on CRAYs. Sobald eine gefunden wurde, sollte die Berechnung am besten gestoppt und nicht auf unbestimmte Zeit bis zu einer unbestimmten Schlussfolgerung fortgesetzt werden. Aus diesem Grund müssen einige Operationen mit NaNs Nicht-NaN-Ergebnisse liefern. Welche Operationen? … Die Ausnahmen sind C-Prädikate „x == x“ und „x! = X“, die für jede unendliche oder endliche Zahl x jeweils 1 und 0 sind, aber umgekehrt, wenn x keine Zahl (NaN) ist; Diese bieten die einzige einfache, nicht außergewöhnliche Unterscheidung zwischen NaNs und Zahlen in Sprachen, denen ein Wort für NaN und ein Prädikat IsNaN (x) fehlt.
Beachten Sie, dass dies auch die Logik ist, die die Rückgabe eines „Not-A-Boolean“ ausschließt. Vielleicht war dieser Pragmatismus fehl am Platz, und der Standard hätte es erfordern müssen isnan( )
, aber das hätte es fast unmöglich gemacht, NaN mehrere Jahre lang effizient und bequem zu nutzen, während die Welt auf die Einführung der Programmiersprache wartete. Ich bin nicht davon überzeugt, dass dies ein vernünftiger Kompromiss gewesen wäre.
Um ehrlich zu sein: Das Ergebnis von NaN == NaN wird sich jetzt nicht ändern. Es ist besser zu lernen, damit zu leben, als sich im Internet zu beschweren. Wenn Sie , dass eine Bestellung Beziehung geeignet für Behälter argumentieren will , sollte auch vorhanden ist , würde ich empfehlen , dafür ein, dass Ihre Lieblings - Programmiersprache die Umsetzung totalOrder
Prädikat standardisiert in IEEE-754 (2008). Die Tatsache, dass es noch nicht für die Gültigkeit von Kahans Besorgnis spricht, die den aktuellen Stand der Dinge motiviert hat.
while (fabs(x - oldX) > threshold)
Verlassen der Schleife werden, wenn Konvergenz auftritt oder ein NaN in die Berechnung eintritt. Der Nachweis des NaN und eines geeigneten Mittels würde dann außerhalb der Schleife erfolgen.