Domanda

Mentre scrivevo alcuni casi di test, e alcuni dei test per verificare il risultato di un NaN.

Ho provato ad utilizzare std::isnan ma i failes asserzione:

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

Dopo aver stampato il valore di x, è venuto fuori che di negativo NaN (-nan) che è del tutto accettabile nel mio caso.

Dopo aver cercato di utilizzare il fatto che NaN != NaN e utilizzando assert(x == x), il compilatore mi fa un 'favore' e ottimizza l'asserzione via.

fare la mia propria funzione isNaN viene ottimizzato via pure.

Come posso controllare sia per l'uguaglianza di NaN e -NaN?

È stato utile?

Soluzione

Questo è imbarazzante.

Il motivo per il compilatore (GCC in questo caso) è stata l'ottimizzazione via il confronto e isnan false tornato è stato perché qualcuno nella mia squadra aveva acceso -ffast-math.

Dalla documentazione:

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

Si noti la frase finale -. -ffast-math è pericoloso

Altri suggerimenti

isnan() dovrebbe avere un comportamento indefinito con -ffast-math.

Questo è quello che uso nella mia suite di 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

Questo appare come un bug nell'implementazione della vostra libreria di isnan() a me. Funziona bene qui in gcc 4.2.1 su Snow Leopard. Tuttavia, che dire di provare questo?

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

Ovviamente, non posso provarlo, dal momento che è std::isnan(-NaN) true sul mio sistema.

Modifica : Con -ffast-math, a prescindere dal commutatore -O, gcc 4.2.1 su Snow Leopard pensa che NAN == NAN è true, come è NAN == -NAN. Questo potrebbe potenzialmente rompere il codice catastroficamente. Vi consiglio lasciando fuori -ffast-math o almeno test per risultati identici in costruisce utilizzando e non lo si utilizza ...

Non c'è C99 isNaN (), che si dovrebbe essere in grado di utilizzare.

Se nell'implementazione non funziona correttamente (che è che?) È possibile implementare il proprio, per reinterpret_casting a lungo e fare IEEE morse magia.

È possibile controllare i bit di numero. IEEE 754 ha definito maschera per NaN:

  • La segnalazione NaN è rappresentata da qualsiasi sequenza di bit tra X'7F80 0001' e X'7FBF FFFF 'o tra X'FF80 0001' e X'FFBF FFFF'.
  • Un tranquillo NaN è rappresentata da qualsiasi modello di bit tra X'7FC0 0000' e X'7FFF FFFF 'o tra X'FFC0 0000' e X'FFFF FFFF'.

Questo potrebbe essere non portabile, ma se si è sicuri circa la vostra platfofm può essere accettabile. Più: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlf101l.doc/xlfopg/fpieee.htm

Questa è basato l'articolo di Wikipedia pubblicato nei commenti. Si noti che è del tutto non testato -. Dovrebbe dare un'idea di qualcosa che si può fare anche se

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

EDIT:. Credo davvero che si dovrebbe considerare un bug con i ragazzi glibc su quello se

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top