Question

Lors de l'écriture des cas de test, et certains des tests pour vérifier le résultat d'un NaN.

J'ai essayé d'utiliser std::isnan mais les failes assert:

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

Après l'impression de la valeur de x, il est apparu qu'il NaN (de -nan) de négatif qui est tout à fait acceptable dans mon cas.

Après avoir essayé d'utiliser le fait que NaN != NaN et en utilisant assert(x == x), le compilateur me fait une « faveur » et optimise la assert loin.

Faire ma propre fonction isNaN est optimisé aussi bien loin.

Comment puis-je vérifier à la fois l'égalité des NaN et -Nan?

Était-ce utile?

La solution

Ceci est gênant.

La raison pour laquelle le compilateur (GCC dans ce cas) a été l'optimisation loin isnan retourné la comparaison et false a été parce que quelqu'un dans mon équipe avait tourné sur -ffast-math.

A partir de la documentation:

-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. 

Notez la phrase se terminant -. -ffast-math est dangereux

Autres conseils

isnan() devrait avoir un comportement non défini avec -ffast-math.

est ce que je l'utilise dans ma suite de test:

#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

Cela ressemble à un bug dans la mise en œuvre de votre bibliothèque de isnan() pour moi. Il fonctionne très bien ici gcc 4.2.1 sur Snow Leopard. Mais qu'en est-essayer cela?

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

De toute évidence, je ne peux pas tester, puisque std::isnan(-NaN) est true sur mon système.

EDIT : Avec -ffast-math, quel que soit le commutateur -O, gcc 4.2.1 sur Snow Leopard pense que NAN == NAN est true, comme NAN == -NAN. Cela pourrait casser le code catastrophiquement. Je vous conseille de quitter ou de -ffast-math au moins pour tester des résultats identiques dans les versions à l'aide et ne pas l'utiliser ...

Il y a C99 isnan () que vous devriez être en mesure d'utiliser.

Si dans votre implémentation ne fonctionne pas correctement (ce qui est que?), Vous pouvez mettre en œuvre vos propres, par reinterpret_casting à long et faire de la magie bit IEEE.

Vous pouvez vérifier les bits du nombre. IEEE 754 a défini un masque de NaN:

  • A de NaN est représenté par un motif de bits entre X'7F80 0001' et X'7FBF FFFF 'ou entre X'FF80 0001' et X'FFBF FFFF'.
  • Un silencieux NaN est représenté par une configuration binaire entre X'7FC0 0000' et X'7FFF FFFF 'ou entre X'FFC0 0000' et X'FFFF FFFF'.

Cela peut être pas portable, mais si vous êtes sûr de votre platfofm il peut être acceptable. En savoir plus: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlf101l.doc/xlfopg/fpieee.htm

est basé sur l'article de wikipedia posté dans les commentaires. Notez qu'il est tout à fait non testé -. Il devrait vous donner une idée de quelque chose que vous pouvez faire si

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

EDIT:. Je pense vraiment que vous devriez envisager de déposer un bug avec les gars glibc sur celui-là si

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top