IsNan implementierung
-
wenn man so eine funktion braucht, macht man sowieso was falsch
-
So, jetz'. Statt otze's Funktion, lieber noch
volatileeinbauen, weil einige Compiler das "versehentlich" optimieren könnten.template<typename T> typename std::enable_if<std::is_floating_point<T>::value, bool>::type isnan(T const val) { T volatile const temp = val; return temp != val; }Test auf Ideone.
-
sachma junge bist du auf kocks?
-
install, setup, configure schrieb:
wenn man so eine funktion braucht, macht man sowieso was falsch
Nö.
-
std::isnan funktioniert ja leider nur auf C++11 compilern zuverlässig (oder? isnan ist ja aus C99 und muss daher wohl nicht in C++03 compilern vorhanden sein. was sagt der Standard dazu?)
1. Wer isNaN braucht, macht wirklich etwas falsch. Wenn das als Eingabe kommt, kann man das noch verstehen, aber innerhalb von Rechnungen sollte man schon selbst darauf achten, dass es nicht NaN wird. Wenn man einmal NaN hat, ist das Kind in den Brunnen gefallen.
2. warum sollte isNan nicht auch auf andere Typen anwendbar sein? Im Default-Fall macht es halt nichts oder gibt false zurück. Aber einfach compilerfehler erzeugen ist doof...
3. Deine Version hat völlig neue Schwierigkeiten. d könnte in einem Register sein, der größer ist als der Datentyp auf dem Stack (siehe so gut wie jede heutige CPU...). Dein volatile kopiert das d dann aber vom Register auf den Stack wodurch du in diesem Fall einen Rundungsfehler erhälst. Für den Vergleich wird temp dann wieder in den größeren Register geladen und der Vergleich geht dank Rundungsfehler schief.
-
otze schrieb:
3. Deine Version hat völlig neue Schwierigkeiten. d könnte in einem Register sein, der größer ist als der Datentyp auf dem Stack (siehe so gut wie jede heutige CPU...).
Im Gegenteil, gerade bei heutigen CPUs gibt es SSE- und SSE2-Register, die in den gleichen Breiten rechnen wie die Variable auf dem Stack belegt. Was du beschreibst ist bei der x87-FPU ein Problem, weil die Register dort 80 Bits breit sind.
Ich bin allerdings kein Floating-Point-Experte, vielleicht meintest du ja einen anderen Effekt.
-
Sone schrieb:
So, jetz'. Statt otze's Funktion, lieber noch
volatileeinbauen, weil einige Compiler das "versehentlich" optimieren könnten.template<typename T> typename std::enable_if<std::is_floating_point<T>::value, bool>::type isnan(T const val) { T volatile const temp = val; return temp != val; }Test auf Ideone.
NaN ist genau so definiert, dass es ungleich mit sich selbst ist. Wenn ein Compiler das "versehentlich" optimiert, ist ein Bugreport an den Compilerhersteller fällig. Die Optimierung ist einfach nur falsch.
-
tntnet schrieb:
Wenn ein Compiler das "versehentlich" optimiert, ist ein Bugreport an den Compilerhersteller fällig. Die Optimierung ist einfach nur falsch.
GCC macht diese Optimierung AFAIK nur mit -ffast-math, was bei -O2 aber standardmäßig nicht aktiviert ist.
-
pyhax schrieb:
tntnet schrieb:
Wenn ein Compiler das "versehentlich" optimiert, ist ein Bugreport an den Compilerhersteller fällig. Die Optimierung ist einfach nur falsch.
GCC macht diese Optimierung AFAIK nur mit -ffast-math, was bei -O2 aber standardmäßig nicht aktiviert ist.
Genau genommen ist es -ffinite-math-only; und dann ist es kein Fehler, wenn der Compiler das macht. Eher hat man es mit einem schizophrenen Programmierer zu tun.
-
Bashar schrieb:
Ich bin allerdings kein Floating-Point-Experte, vielleicht meintest du ja einen anderen Effekt.
Ich meine schon den Effekt. Aber dafür muss der Prozessor erstmal mit den SSE--Registern rechnen. Afaik macht das aber kein Compiler für einzelne floats, solange man ihn nicht dazu zwingt.
-
otze schrieb:
1. Wer isNaN braucht, macht wirklich etwas falsch. Wenn das als Eingabe kommt, kann man das noch verstehen, aber innerhalb von Rechnungen sollte man schon selbst darauf achten, dass es nicht NaN wird. Wenn man einmal NaN hat, ist das Kind in den Brunnen gefallen.
Wer sagt denn, dass ich mit NaN rechne? NaN dient in dem Fall lediglich dazu auszudrücken, dass sich etwas beliebig weit ausdehnen kann.
Die std steht nicht zur Verfügung. Darum die eigene Implementierung.
-
otze schrieb:
Afaik macht das aber kein Compiler für einzelne floats, solange man ihn nicht dazu zwingt.
Die 64-bit-Version vom MSVC 2010 macht das.