Warum ist NaN – NaN == 0,0 mit dem Intel C++ Compiler?

Lesezeit: 3 Minuten

Benutzeravatar von imallett
imallett

Es ist bekannt, dass sich NaNs in der Arithmetik ausbreiten, aber ich konnte keine Demonstrationen finden, also habe ich einen kleinen Test geschrieben:

#include <limits>
#include <cstdio>

int main(int argc, char* argv[]) {
    float qNaN = std::numeric_limits<float>::quiet_NaN();

    float neg = -qNaN;

    float sub1 = 6.0f - qNaN;
    float sub2 = qNaN - 6.0f;
    float sub3 = qNaN - qNaN;

    float add1 = 6.0f + qNaN;
    float add2 = qNaN + qNaN;

    float div1 = 6.0f / qNaN;
    float div2 = qNaN / 6.0f;
    float div3 = qNaN / qNaN;

    float mul1 = 6.0f * qNaN;
    float mul2 = qNaN * qNaN;

    printf(
        "neg: %f\nsub: %f %f %f\nadd: %f %f\ndiv: %f %f %f\nmul: %f %f\n",
        neg, sub1,sub2,sub3, add1,add2, div1,div2,div3, mul1,mul2
    );

    return 0;
}

Das Beispiel (läuft hier live) erzeugt im Grunde das, was ich erwarten würde (das Negative ist ein bisschen seltsam, aber es macht irgendwie Sinn):

neg: -nan
sub: nan nan nan
add: nan nan
div: nan nan nan
mul: nan nan

MSVC 2015 produziert etwas Ähnliches. Allerdings erzeugt Intel C++ 15:

neg: -nan(ind)
sub: nan nan 0.000000
add: nan nan
div: nan nan nan
mul: nan nan

Speziell, qNaN - qNaN == 0.0.

Das… kann nicht stimmen, oder? Was sagen die einschlägigen Standards (ISO C, ISO C++, IEEE 754) dazu und warum gibt es ein unterschiedliches Verhalten zwischen den Compilern?

  • Javascript und Python(numpy) haben dieses Verhalten nicht. Nan-NaN ist NaN. Auch Perl und Scala verhalten sich ähnlich.

    – Paulus

    25. August 2015 um 5:18 Uhr


  • Möglicherweise haben Sie unsichere mathematische Optimierungen aktiviert (das Äquivalent von -ffast-math auf gcc)?

    – Matteo Italien

    25. August 2015 um 5:21 Uhr

  • @nm: Stimmt nicht. Anhang F, der optional, aber normativ ist, wenn er unterstützt wird, und erforderlich, um das Gleitkommaverhalten zu spezifizieren überhauptintegriert im Wesentlichen IEEE 754 in C.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    25. August 2015 um 5:25 Uhr

  • Wenn Sie nach dem IEEE 754-Standard fragen möchten, erwähnen Sie ihn irgendwo in der Frage.

    – n. 1.8e9-wo-ist-meine-Aktie m.

    25. August 2015 um 5:27 Uhr

  • ich war sicher Diese Frage bezog sich auf JavaScript aus dem Titel.

    – Mike G

    25. August 2015 um 12:51 Uhr

  • Ich habe das gerade selbst ausprobiert. In der Tat behebt die Angabe von „precision“ oder „strict“ das Problem.

    – imallett

    25. August 2015 um 5:30 Uhr

  • Ich möchte die Entscheidung von Intel unterstützen, dies standardmäßig zu tun /fp:fast: wenn du etwas willst sichersollten Sie wahrscheinlich besser vermeiden, dass NaNs überhaupt auftauchen, und verwenden Sie sie im Allgemeinen nicht == mit Fließkommazahlen. Sich auf die seltsame Semantik zu verlassen, die IEEE754 NaN zuweist, verlangt nach Ärger.

    – linksherum

    25. August 2015 um 14:24 Uhr

  • @leftaroundabout: Was findest du seltsam an NaN, abgesehen von der meiner Meinung nach schrecklichen Entscheidung, dass NaN!=NaN wahr zurückgibt?

    – Superkatze

    25. August 2015 um 16:41 Uhr

  • NaNs haben wichtige Verwendungszwecke – sie können Ausnahmesituationen erkennen, ohne dass nach jeder Berechnung Tests erforderlich sind. Nicht jeder Fließkommaentwickler braucht sie, aber verwerfen Sie sie nicht.

    – Bruce Dawson

    25. August 2015 um 17:03 Uhr

  • @supercat Aus Neugier bist du mit der Entscheidung einverstanden NaN==NaN Rückkehr false?

    – Kyle Strand

    25. August 2015 um 18:52 Uhr

  • Beachte das mit -ffast-math, gcc entspricht nicht mehr ISO 9899:2011 in Bezug auf Fließkomma-Arithmetik.

    – fuz

    1. September 2015 um 11:12 Uhr

  • @FUZxxl Ja, der Punkt ist das beide Compiler haben einen nicht konformen Gleitkommamodus, es ist nur so, dass icc standardmäßig auf diesen Modus eingestellt ist und gcc nicht.

    – zol

    1. September 2015 um 22:06 Uhr

  • Nur um Öl ins Feuer zu gießen, ich mag Intels Entscheidung, schnelle Mathematik standardmäßig zu aktivieren. Der springende Punkt bei der Verwendung von Floats ist es, einen hohen Durchsatz zu erzielen.

    – Navin

    14. September 2015 um 8:44 Uhr


1426960cookie-checkWarum ist NaN – NaN == 0,0 mit dem Intel C++ Compiler?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy