Compruebe si un número es + -Inf o NaN

Por el motivo de la robustez, quiero verificar si un número flotante es IEEE-754 + -Inf o IEEE-754 Nan. Mi código está en lo siguiente, quiero saber si es correcto:

#define PLUS_INFINITE (1.0f/0.0f) #define MINUS_INFINITE (-1.0f/0.0f) #define NAN (0.0f/0.0f) float Local_Var; /*F is a float numnber.*/ if((unsigned long)(F) == 0x7f800000ul) { Local_Var = PLUS_INFINITE; } elseif((unsigned long)(F) == 0xff800000ul) { Local_Var = MINUS_INFINITE; } /*fraction = anything except all 0 bits (since all 0 bits represents infinity).*/ elseif((((unsigned long)(F) & 0x007ffffful) != 0ul ) &&((unsigned long)(F) == 0x7f800000ul)) || (((unsigned long)(F) & 0x807ffffful) != 0ul ) && ((unsigned long)(F) == 0xff800000ul)) { Local_Var = NAN; } else{} 

C99 tiene macros para la clasificación de números de punto flotante:

fpclassify(x) devuelve uno de:

  • FP_NAN : x no es un número;
  • FP_INFINITE : x es más o menos infinito;
  • FP_ZERO : x es cero;
  • FP_SUBNORMAL : x es demasiado pequeño para ser representado en formato normalizado o
  • FP_NORMAL : número de punto flotante normal, es decir, ninguno de los anteriores.

También hay accesos directos que verifican una de estas clases, que devuelven un valor distinto de cero si x es lo que:

  isfinite(x) isnormal(x) isnan(x) isinf(x) 

El argumento x puede ser cualquier expresión de punto flotante; Las macros detectan el tipo de argumento y trabajan para float y double .

EDITAR : Como no desea usar (o no puede usar) , puede usar otras propiedades de nan e inf para clasificar sus números:

  • nan compara falso a todos los números, incluso a sí mismo;
  • inf es mayor que FLT_MAX ;
  • -inf es más pequeño que -FLT_MAX .

Asi que:

 #include  #include  #include  int main() { float f[] = { 0.0, 1.0, FLT_MAX, 0.0 / 0.0, 1.0/0.0, -1.0/0.0 }; int i; for (i = 0; i < 6; i++) { float x = f[i]; int is_nan = (x != x); int is_inf = (x < -FLT_MAX || x > FLT_MAX); printf("%20g%4d%4d\n", x, is_nan, is_inf); } return 0; } 

En esta solución, debe adaptar los límites si desea utilizar el double .

Casting flota a largos como que está mal. Debe ser una unión o un puntero de tipo punted.

Aquí hay un ejemplo de trabajo de dietlibc (con dobles):
https://github.com/ensc/dietlibc/blob/master/lib/__isinf.c https://github.com/ensc/dietlibc/blob/master/lib/__isnan.c

Musl tiene un fpclassify más corto, y también constantes adecuadas para flotadores:
http://git.musl-libc.org/cgit/musl/tree/src/math/__fpclassifyf.c

Lo mejor es usar las funciones fpclassify() de @M Oehm answer

Alternativas:

 float F; if (F <= FLT_MAX) { if (F >= -FLT_MAX) { puts("Finite"); } else { puts("-Infinity"); } } else { if (F > 0) { puts("+Infinity"); } else { puts("NaN"); } } 

Si el código quiere meterse con los bits y asumiendo que float está en formato binary32 :

 assert(sizeof (float) == sizeof (uint32_t)); union { float f; uint32_t u32; } x; xf = F; 

Las máscaras dependen del endian relativo de float y uint32_t endian. Suelen ser los mismos.

 // Is F one of the 3 special: +inf, -inf, NaN? if (x.u32 & 0x7F800000 == 0x7F800000) { if (x.u32 & 0x007FFFFF) { puts("NaN"); } else if (x.u32 & 0x80000000) { puts("-Inf"); } else { puts("+Inf"); } }