2016-07-08 3 views
18

In https://github.com/numpy/numpy/issues/6428 scheint die Ursache für den Fehler zu sein, dass bei simd.inc.src:543 ein Compiler !(tmp == 0.) zu tmp != 0. optimiert.Fälle, in denen float == und! = Keine direkten Gegensätze sind

A comment sagt, dass diese „nicht ganz das gleiche.“ Aber gibt keine Details an. NaNs sind weiter oben erwähnt, aber ein Test zeigt, dass ein NaN im Vergleich zu 0. der erwartete Weg ist.

In welchen Fällen können == und != beide wahr/falsch zurückgeben?

Oder die Diskrepanz ist in einem anderen Feld - z.B. Rückkehr Werte, die den gleichen Wahrheitswert haben, aber anders als Ints (aber Tests haben gezeigt, auch das scheint nicht der Fall ist) ?

+0

Wenn 'f'' NaN' sein kann, ist es kein 'int'. –

+0

Nan kann nicht 0 werden. Da 0 eine Zahl ist, bedeutet NaN keine Zahl. Also sagst du, wenn du das tust "int a = 0;" a ist ein NaN? – amanuel2

+2

Entschuldigung, wenn mir etwas offensichtlich fehlt, aber: Wo in diesem Thread identifizieren sie das als die Ursache? Die nächste Referenz, die ich sehe, beginnt mit "Ich werde raten"! Wie auch immer, dieser verknüpfte Fehler scheint näher zu sein: https://github.com/numpy/numpy/pull/6438 –

Antwort

7

Ein Kommentar sagt, dass diese "nicht ganz die gleiche Sache sind." Aber gibt keine Details an. NaNs werden weiter unten erwähnt, aber ein Test zeigt, dass ein NaN mit 0 verglichen wird.

Was sind die Fälle, in denen == und! = Können sowohl return true/false?

Der Standard sagt:

Die == (gleich) und != (nicht gleich) Betreiber die relationalen Operatoren mit Ausnahme ihrer niedrigere Priorität analog sind. [...] Für jedes Paar von Operanden, genau eine der Beziehungen gilt.

(C2011, 6.5.9/3; Hervorhebung hinzugefügt)

daher für alle Ausdrücke X und Y, die als Operanden dieser Operatoren gemeinsam erlaubt sind, müssen (X) != (Y) zum gleichen Ergebnis bewerten, wie !((X) == (Y)). Wenn sie in der Praxis nicht gefunden werden, dann ist der Compiler, der dieses Ergebnis lieferte, in dieser Hinsicht nicht konform. Wenn diese Nichtkonformität unerwartet ist, stellt dies einen Fehler im Compiler dar.

Außerdem beobachte ich, dass 6.5.9/3 nur so viel zu NaNs, Unendlichkeiten gilt, und subnormals wie für alle anderen Operanden. NaNs sind speziell in Bezug auf diese Operatoren aus einem anderen Grund: NaNs vergleichen ungleich zu allen Operanden, einschließlich sich selbst (angenommen IEEE Semantik).

+1

Okay, es sieht so aus, als müsste ich letztendlich [den Autor des Kommentars auf seiner Aussage anrufen] (https://github.com/numpy/numpy/issues/6428#issuecomment-231404458), um diese Farce zu beenden. –

+1

@ivan_pozdeev Es ist möglich, dass der Code mit '-ffast-math' kompiliert wird, oder in diesem Fall ist das Verhalten möglicherweise nicht genau richtig. – fuz

+1

@ivan_pozdeev, FUZxxls Beispiel wäre ein Fall, in dem der Compiler nicht konform, aber nicht fehlerhaft ist, da er dokumentiert, dass die Verwendung der Option zu Nichtkonformität führen kann (und deshalb muss das Verhalten auch explizit über eine Option aktiviert werden). . Beachten Sie, dass der genannte numpy Bug mit dem MSVC-Build zusammenhängt und MSVC dafür bekannt ist, dass er nicht konform und fehlerhaft ist. –

0

Von dem verlinkten Beitrag:

Charris am 9. Oktober kommentiert 2015

Ich werde die !(tmp == 0.) erraten ist tmp != 0. optimiert, was nicht ganz dasselbe ist.

Kommentar von OP:

Der Autor sagt, es ist eine Vermutung, aber sie sind sehr positiv, dass !(tmp==0.) und tmp!=0. nicht gleichwertig sind und dass auszudrücken, als ob es allgemein bekannt ist

Wie Versöhnen wir diese beiden?

Offensichtlich sind sie logisch gleichwertig. Aber im Hinblick auf die Implementierung können sie es nicht sein. Ein Compiler könnte !(a == b) als Test a == b implementieren, gefolgt von einer Negation. Alternativ kann der Ausdruck optimiert werden und direkt a != b getestet werden. Der sich ergebende Assembly-Code wäre in diesen beiden Fällen unterschiedlich. Das gleiche Ergebnis sollte (muss) erreicht werden, aber die Ausführungszeit könnte unterschiedlich sein.

"nicht ganz die gleiche Sache" wäre einfach eine Bestätigung, dass !(a == b) und a != b tatsächlich unterschiedliche Kombinationen von Zeichen sind und der Compiler könnte etwas technisch anders mit ihnen tun, die das gleiche Ergebnis liefern muss. Und wenn unterschiedliche Ergebnisse beobachtet werden, dann könnte ein Fehler im Compiler existieren.

+1

Was sagst du? Sie müssen das gleiche Ergebnis zurückgeben. Wie die CPU dorthin kommt, hat keine Konsequenzen. Alles andere ist ein Compiler-Fehler. Dann "Das gleiche Ergebnis sollte (muss) erreicht werden, aber die Ausführungszeit könnte anders sein." - was dazu führen würde, dass so viele Tests fehlschlagen, weil ...? –

+0

@underscore_d Ich sage der OP fehlinterpretierte Charris "was nicht ganz der gleiche" Kommentar ist. Charris spricht von Implementierungsunterschieden, und das OP liest es als logische Äquivalenz. All dies wird durch einen tatsächlich beobachteten Unterschied in den Ergebnissen erschwert, der den Erwartungen beider Parteien widerspricht. Das OP versucht herauszufinden, in welchem ​​Fall die logische Äquivalenz aufgrund von Charris Kommentar zusammenbricht. Charris Kommentar bezog sich jedoch nicht auf die logische Äquivalenz der beiden Tests, sondern auf die daraus resultierende Implementierung der Tests. – AJNeufeld

Verwandte Themen