Frage

Während einige Testfälle zu schreiben, und einige der Tests prüfen das Ergebnis einer NaN.

Ich habe versucht, mit std::isnan aber die assert failes:

Assertion `std::isnan(x)' failed.

Nach dem Drucken der Wert von x, stellte sich heraus, dass es negative NaN (-nan), die völlig akzeptabel in meinem Fall ist.

Nach dem Versuch, die Tatsache zu nutzen, dass NaN != NaN und mit assert(x == x), der Compiler tut mir einen ‚Gefallen‘ und optimiert die assert entfernt.

Indem ich isNaN Funktion entfernt und optimiert wird.

Wie kann ich sowohl für die Gleichstellung von NaN überprüfen und -NaN?

War es hilfreich?

Lösung

Das ist peinlich.

Der Grund der Compiler (GCC in diesem Fall) wurde den Vergleich und isnan zurück false Optimierung entfernt wurde, weil jemand in meinem Team auf -ffast-math worden war.

Aus der Dokumentation:

-ffast-math
    Sets -fno-math-errno, -funsafe-math-optimizations,
    -fno-trapping-math, -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 should never be turned on by any -O option since it can result in incorrect output for programs which depend on an exact implementation of IEEE or ISO rules/specifications for math functions. 

Beachten Sie die Endung Satz -. -ffast-math ist unsicher

Andere Tipps

isnan() wird erwartet, dass nicht definiertes Verhalten mit -ffast-math haben.

Dies ist, was ich in meinem Test-Suite verwendet werden:

#if defined __FAST_MATH__
#   undef isnan
#endif
#if !defined isnan
#   define isnan isnan
#   include <stdint.h>
static inline int isnan(float f)
{
    union { float f; uint32_t x; } u = { f };
    return (u.x << 1) > 0xff000000u;
}
#endif

sieht wie folgt aus einem Fehler in Ihrer Bibliothek Implementierung von isnan() mir. Es funktioniert gut, hier auf gcc 4.2.1 auf Snow Leopard. Doch was diese versuchen?

std::isnan(std::abs(yourNanVariable));

Natürlich, ich kann es nicht testen, da std::isnan(-NaN) ist true auf meinem System.

Bearbeiten : Mit -ffast-math, unabhängig von dem -O Schalter, gcc 4.2.1 auf Snow Leopard denkt, dass NAN == NAN true ist, wie NAN == -NAN ist. Dies könnte möglicherweise Code katastrophal brechen. Ich würde raten ab -ffast-math oder zumindest zu verlassen in der Prüfung auf identische Ergebnisse Builds verwenden und nicht verwenden es ...

Es gibt C99 isnan (), die Sie sollten verwendet werden können.

Wenn in Ihrer Implementierung es nicht richtig funktioniert (welches ist das?) Sie Ihre eigenen implementieren können, indem sie lange reinterpret_casting und tun IEEE Magie Bit.

Sie können die Bits Nummer überprüfen. 754 IEEE definiert Maske für NaN:

  • A Signalisierungs NaN durch jedes Bitmuster zwischen X'7F80 0001' und X'7FBF FFFF 'oder zwischen X'FF80 0001' und X'FFBF FFFF' dargestellt ist.
  • Ein ruhiges NaN durch jedes Bitmuster zwischen X'7FC0 0000' und X'7FFF FFFF 'oder zwischen X'FFC0 0000' und X'FFFF FFFF' dargestellt wird.

Dies könnte nicht tragbar sein, aber wenn Sie sicher Ihre platfofm sind, kann es akzeptabel sein. Mehr: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlf101l.doc/xlfopg/fpieee.htm

Dies ist der Wikipedia-Artikel veröffentlicht in den Kommentaren basiert. Beachten Sie, dass es völlig ungetestet -. Es sollte Ihnen eine Vorstellung von etwas geben Sie aber tun können,

bool reallyIsNan(float x)
{
    //Assumes sizeof(float) == sizeof(int)
    int intIzedX = *(reinterpret_cast<int *>(&x));
    int clearAllNonNanBits = intIzedX & 0x7F800000;
    return clearAllNonNanBits == 0x7F800000;
}

EDIT:. Ich glaube wirklich, sollten Sie auf, dass man zwar einen Fehler mit den glibc Jungs Einreichung betrachten

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top