NaN und -ffast-math

C/C++ relevanter Post:

Wer die Optimierung -ffast-math beim gcc-Compiler eingeschaltet hat, wird irgendwann feststellen, dass der isnan-Vergleich nicht mehr möglich ist.

Ursache

Das Problem ist das gcc-Compiler-Flag -ffinite-math-only. Diese Optimierung lässt nämlich explizit die Annahme zu, dass alle Gleitkommaberechnungen weder NaN noch +-Inf sind. Und genau diese Annahme ist es, welche jede Vergleiche mit nan sofort als fehlgeschlagen abstempelt.

Behebung

Entweder -ffast-math abschalten, oder explitzit noch den Flag -fno-finite-math-only dazugeben. Beispiel:

Alternativ kann man auch eine alternative nan-Routine verwenden, die im Beispielprogramm erklärt sind.

Beispielprogramm

[Download]

Das Programm erstellt ein NaN als Variable x und lässt danach einige Vergleiche zu. Auf Stackoverflow werden drei verschiedene Lösungen angeboten. Bei mir (gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2) funktionieren Lösungen 2 und drei, ich empfehle ausdrücklich Lösung zwei, weil sie mir als die "sauberere" der beiden Möglichkeiten erscheint

Wichtig: Nicht float durch double ersetzen, auch wenn man ein double vergleichen möchte. Einfach so benutzen!

 

Anmerkung am Schluss

-ffast-math niemals leichtsinnig verwenden. Vor allem nicht mit Optimierungs-Flags. Schaut euch mal die Manpage zu -ffast-math an

-ffast-math
Sets -fno-math-errno, -funsafe-math-optimizations,
-ffinite-math-only, -fno-rounding-math, -fno-signaling-nans and
-fcx-limited-range.

This option causes the preprocessor macro "__FAST_MATH__" to be
defined.

This option is not turned on by any -O option besides -Ofast since
it can result in incorrect output for programs that depend on an
exact implementation of IEEE or ISO rules/specifications for math
functions. It may, however, yield faster code for programs that do
not require the guarantees of these specifications.