2015-08-26 9 views
13

Als ich Code debugging, fand ich, dass GCC und Clang beide für 0.0/0.0 nan liefern, was ich erwartete, aber GCC ergibt eine Nan mit dem Vorzeichen Bit auf 1 gesetzt, während Clang es auf 0 setzt (in Übereinstimmung mit ICC , wenn ich mich richtig erinnere).Warum ergibt GCC -nan und clang und Intel + nan für 0.0/0.0?

nun offenbar sind beide Formen erlaubt, aber ich halte fragen, warum 0.0/0.0 würde GCC Ausgang ein „negatives“ Ergebnis (Druck es gibt -nan) machen, und -(0.0/0.0) gibt ein „positives“ Ergebnis? Was noch verwirrender ist, ist, dass -0.0/0.0 wieder "negativ" ist. Ist das eine ständige Falte Seltsamkeit?

bearbeiten

Eigentlich ist es die konstante Faltung, dass es eine positive nan macht. Wenn ich die Berechnung zur Laufzeit zwingen, erhalte ich negativ nan sowohl GCC und Clang

volatile float zero = 0.0; 
std::cout << (zero/zero); // -nan 

Kann jemand etwas Licht in diese Sched bitte? Ist das Vorzeichen Bit auf der x86 FPU auf 1 gesetzt?

Antwort

7

IEEE-754 spezifiziert nicht das Zeichen eines NaN:

Wenn entweder ein Eingang oder Ergebnis ist NaN enthält diese Norm nicht das Vorzeichen einer NaN interpretieren. Beachten Sie jedoch, dass Operationen auf Bit Strings - kopieren, negieren, abs, copySign - das Vorzeichen-Bit eines NaN-Ergebnisses angeben, manchmal basierend auf dem Vorzeichen-Bit eines NaN-Operanden. Das logische Prädikat totalOrder wird auch vom Vorzeichenbit eines NaN-Operanden beeinflusst. Für alle anderen Operationen gibt dieser Standard das Vorzeichenbit eines NaN-Ergebnisses nicht an, selbst wenn nur ein Eingang NaN, oder wenn das NaN aus einer ungültigen Operation erzeugt wird.

Jetzt schauen wir uns die Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 1: Basic Architecture.

Darin gibt Intel in diesem Fall einen spezifischen Wert von NaN an, der QNaN Floating-Point Indefinite genannt wird (siehe Tabelle 4-1), der bei #IA (ungültige arithmetische Ausnahme) zurückgegeben wird (siehe Tabelle 8-10). Suchen Sie nach Division 0 durch 0.

Sie sehen, dass für diesen Wert das Vorzeichen Bit festgelegt ist.

+0

Ah ich sehe. Daher scheinen clang und icc inkonsistente Ergebnisse zu liefern, je nachdem, ob Sie direkt 0/0 berechnen oder Optimierungen aktivieren. Ist das absichtlich? –

+0

Nicht sicher, was du meinst. Der Compiler kann mit dem Vorzeichen-Bit machen, was er will. Das Vorzeichenbit ist im IEEE-Standard nicht spezifiziert. Es ist das Recht der Compiler, + NaN oder -NaN hier zu verwenden. X86-Intel-CPUs ergeben jedoch immer ein NaN mit negativem Vorzeichenbit, das auch gemäß dem Standard gültig ist. Einige Compiler wissen vielleicht etwas über dieses Hardware-Verhalten, andere nicht, und einige interessieren sich wahrscheinlich nicht dafür. Wenn Sie neugierig sind, lautet die entsprechende Quelle llvm/lib/Support/APFloat.cpp, die divideSpecial-Methode. Ich kann wirklich nicht gestört werden, in GCC-Quelle zu tauchen ^^ – marc

+0

haha ​​danke, ich verstehe. –