tipos sirve que programacion para lenguaje historia ejemplos caracteristicas c++ floating-point nan

sirve - ¿Cómo trata C++ con NAN? ¿Hay una forma estándar o es compilador dependiente?



para que sirve c++ (5)

En un programa que necesita procesar la función sin (x) / x, encontré un problema NAN, simplifiqué el problema en el siguiente código:

#include <iostream> #include <cmath> int main() { std::cout.precision(15); //This line compiles and run in g++, but does not compile in Visual Studio 2013 std::cout << 0.0/0.0 << std::endl; //This line compiles and run in both g++ and VS2013 std::cout << std::sin(0.0)/0.0 << std::endl; return 0; }

En g ++, la salida es: -nan -nan, en VS2013, la salida es: -1.IND, porque la primera línea no se compila, así que la comenté.

Mis preguntas son:

  1. ¿Qué significa este ''-1.IND''?

  2. Parece que el procesamiento NAN depende del compilador, ¿debería esto estar estandarizado en C ++? ¿Por qué?

  3. Usé este truco para lidiar con este problema:

    double sinc(double x) { if(x == 0.0) return 1.0; return std::sin(x)/x; }

¿Es este el camino correcto?

EDIT: otra pregunta, 4. ¿por qué VS2013 trata con 0.0 / 0.0 y sin (0.0) /0.0 de manera diferente?


  1. La compilación de la expresión double res = 0.0 / 0.0 falla porque el compilador intenta optimizar el código que determina la expresión "no válida". No puede optimizar la expresión como sin(x) / 0.0 porque no es capaz de simplificar y "optimizar" código como este ".
  2. La visualización de valores especiales de double tipo de datos depende de la plataforma. Pero la representación depende de la arquitectura . Para verificar esto, puede ejecutar esta función en diferentes arquitecturas: template<typename T> void inspect(T v1, T v2) { T i_val = v1; i_val /= v2; size_t len = sizeof(T); int* bit_repr = (int*)(&i_val); for (int i = 0; i < (len / sizeof(int)); i ++) { std::bitset<sizeof(int) * 8> bs(*(bit_repr + i)); std::cout << bs; } std::cout << std::endl; } template<typename T> void inspect(T v1, T v2) { T i_val = v1; i_val /= v2; size_t len = sizeof(T); int* bit_repr = (int*)(&i_val); for (int i = 0; i < (len / sizeof(int)); i ++) { std::bitset<sizeof(int) * 8> bs(*(bit_repr + i)); std::cout << bs; } std::cout << std::endl; }

Llame a la función anterior con los siguientes argumentos:

inspect<double>(0.0, 0.0); inspect<double>(1.0, 0.0); inspect<double>(-1.0, 0.0);


Esto podría ser útil: C ++ 11 (por lo tanto, VS2013) tiene alguna característica que entender si un número dado es NAN o es finito. Utilice std :: isnan () o std :: isfinite ()


Hay preguntas similares a las suyas respondidas en SO:

1. ¿Qué significa este ''-1.IND''?

Consulte ¿Qué significa 1. # INF00, -1. # IND00 y -1. # IND?

2. Parece que el procesamiento NAN depende del compilador, ¿debería esto estar estandarizado en C ++? ¿Por qué?

Vea Algunas cosas acerca de la división por cero en C (dice C, pero habla de C ++)

3. Utilicé este truco para lidiar con este problema:

double sinc(double x) { if(x == 0.0) return 1.0; return std::sin(x)/x; }

¿Es este el camino correcto?

Sí, esta implementación de la función sinc funcionará y (Gracias a @MSalters por el comentario) es matemáticamente correcta; sin embargo, tenga en cuenta que, si bien funcionará en este caso, no haga el hábito de comparar tipos double con == .


La conformidad completa con el estándar de punto flotante IEEE es opcional en los estándares C y C ++. Esto se debe a que, por razones que nunca han sido claras para mí, los diseñadores de CPU odian el estándar de punto flotante IEEE. No tengo conocimiento de ninguna CPU que implemente la especificación completa de manera correcta y eficiente. (Lo mejor que puede tener, por lo que sé, es una CPU que sea rápida y correcta para los números finitos normales, pero sufre ralentizaciones de múltiples órdenes de magnitud si desea trabajar con denormales, infinito y NaN).

Los estándares de C y C ++ están escritos por compiladores. La gente del compilador quiere poder generar código de máquina que se ejecute rápidamente en las CPU reales, y saben que las CPU reales reducen los límites en el punto flotante IEEE, por lo que no hacen que la conformidad total con el punto flotante IEEE sea un requisito de idioma.


Para agregar una respuesta para (4), sin(x) es una función de tiempo de ejecución y, por lo tanto, sin(0.0)/0.0 se maneja como una expresión que se evalúa en tiempo de ejecución. OTOH, 0.0/0.0 es manejado completamente por el compilador, por lo que detecta el problema. Un detalle de implementación de su versión de Visual Studio, y no algo con lo que pueda contar.