Negativo NaN no es un NaN?
Pregunta
Al escribir algunos casos de prueba, y algunas de las pruebas para comprobar el resultado de un NaN.
He intentado utilizar std::isnan
pero los failes de aserción:
Assertion `std::isnan(x)' failed.
Después de imprimir el valor de x
, resultó que de negativo NaN (-nan
) que es totalmente aceptable en mi caso.
Después de tratar de utilizar el hecho de que NaN != NaN
y el uso de assert(x == x)
, el compilador me hace un 'favor' y optimiza la aserción de distancia.
Haciendo mi propia función isNaN
se está optimizando lejos también.
¿Cómo puedo comprobar tanto la igualdad de NaN y -nan?
Solución
Esto es embarazoso.
La razón por la que el compilador (GCC en este caso) ha sido optimizar la comparación de distancia y isnan
regresado false
fue porque alguien de mi equipo se había convertido en -ffast-math
.
A partir de los documentos:
-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.
Aviso de la frase que termina -. -ffast-math
no es seguro
Otros consejos
Se espera que isnan()
tener un comportamiento indefinido con -ffast-math
.
Esto es lo que yo uso en mi banco de pruebas:
#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
Esto parece un error en la ejecución de su biblioteca de isnan()
a mí. Trabaja muy bien aquí en gcc 4.2.1 en Snow Leopard. Sin embargo, ¿qué hay de tratar esto?
std::isnan(std::abs(yourNanVariable));
Obviamente, no puedo probarlo, ya que es std::isnan(-NaN)
true
en mi sistema.
Editar : Con -ffast-math
, independientemente del interruptor -O
, gcc 4.2.1 en Snow Leopard piensa que es NAN == NAN
true
, como es NAN == -NAN
. Esto podría romper el código de manera catastrófica. Yo le aconsejaría dejando fuera -ffast-math
o al menos las pruebas de resultados idénticos en construye utilizando y no usarlo ...
Hay C99 isnan () que debe ser capaz de utilizar.
Si en su aplicación no funciona correctamente (que es eso?) Puede implementar su propia, por reinterpret_casting a largo y haciendo IEEE mordió magia.
Puede comprobar los bits de número. IEEE 754 ha definido máscara para NaN:
- señalización A NaN está representado por cualquier patrón de bits entre X'7F80 0001' y X'7FBF FFFF 'o entre X'FF80 0001' y X'FFBF FFFF'.
- A tranquila NaN está representado por cualquier patrón de bits entre X'7FC0 0000' y X'7FFF FFFF 'o entre X'FFC0 0000' y X'FFFF FFFF'.
Esto podría ser no es portátil, pero si está seguro acerca de su platfofm puede ser aceptable. Más: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlf101l.doc/xlfopg/fpieee.htm
Esta está basada en el artículo de wikipedia publicado en los comentarios. Tenga en cuenta que es totalmente no probado -. Debe darle una idea de algo que se puede hacer sin embargo
bool reallyIsNan(float x)
{
//Assumes sizeof(float) == sizeof(int)
int intIzedX = *(reinterpret_cast<int *>(&x));
int clearAllNonNanBits = intIzedX & 0x7F800000;
return clearAllNonNanBits == 0x7F800000;
}
EDIT:. Realmente creo que debería considerar la presentación de un error con los chicos glibc en que uno, aunque