2008-12-07 66 views
55

Estoy jugando con un código C usando flotadores, y estoy obteniendo 1. # INF00, -1. # IND00 y -1. # IND cuando intento imprimir flotadores en la pantalla. ¿Qué significan esos valores?¿Qué significa 1. # INF00, -1. # IND00 y -1. # IND significa?

Creo que 1. # INF00 significa infinito positivo, pero ¿qué pasa con -1. # IND00 y -1. # IND? También vi a veces este valor: 1. $ NaN que no es un número, pero ¿qué causa esos valores extraños y cómo pueden ayudarme con la depuración?

Estoy usando MinGW que creo que usa IEEE 754 representación para los números de punto flotante.

¿Alguien puede enumerar todos los valores no válidos y lo que significan?

Respuesta

61

De IEEE floating-point exceptions in C++:

This page will answer the following questions.

  • My program just printed out 1.#IND or 1.#INF (on Windows) or nan or inf (on Linux). What happened?
  • How can I tell if a number is really a number and not a NaN or an infinity?
  • How can I find out more details at runtime about kinds of NaNs and infinities?
  • Do you have any sample code to show how this works?
  • Where can I learn more?

These questions have to do with floating point exceptions. If you get some strange non-numeric output where you're expecting a number, you've either exceeded the finite limits of floating point arithmetic or you've asked for some result that is undefined. To keep things simple, I'll stick to working with the double floating point type. Similar remarks hold for float types.

Debugging 1.#IND, 1.#INF, nan, and inf

If your operation would generate a larger positive number than could be stored in a double, the operation will return 1.#INF on Windows or inf on Linux. Similarly your code will return -1.#INF or -inf if the result would be a negative number too large to store in a double. Dividing a positive number by zero produces a positive infinity and dividing a negative number by zero produces a negative infinity. Example code at the end of this page will demonstrate some operations that produce infinities.

Some operations don't make mathematical sense, such as taking the square root of a negative number. (Yes, this operation makes sense in the context of complex numbers, but a double represents a real number and so there is no double to represent the result.) The same is true for logarithms of negative numbers. Both sqrt(-1.0) and log(-1.0) would return a NaN, the generic term for a "number" that is "not a number". Windows displays a NaN as -1.#IND ("IND" for "indeterminate") while Linux displays nan. Other operations that would return a NaN include 0/0, 0*∞, and ∞/∞. See the sample code below for examples.

In short, if you get 1.#INF or inf, look for overflow or division by zero. If you get 1.#IND or nan, look for illegal operations. Maybe you simply have a bug. If it's more subtle and you have something that is difficult to compute, see Avoiding Overflow, Underflow, and Loss of Precision. That article gives tricks for computing results that have intermediate steps overflow if computed directly.

+3

Sé que OP realmente no pidió esto, pero como una prueba práctica, 'myfloat == myfloat' devolverá falso si tiene uno de estos valores mágicos. – tenpn

+7

@tenpn En realidad en C++, + infinito == + infinito. Intente comprobar 1.0/0.0: '1. # INF00' ==' 1. # INF00' devuelve verdadero, '-1. # INF00' ==' -1. # INF00' devuelve verdadero, pero '1. # INF00' = = '-1. # INF00' es falso. – bobobobo

+2

No estoy seguro acerca de otras configuraciones, pero en Windows 7/Visual studio 2010. float nan = sqrtf (-1.0f); nan == nan; // evalúa como verdadero ... en contra de lo que dijo tenpn ... (Comentario de Yevgen V) – Jeff

3

Para aquellos de ustedes en un entorno .NET lo siguiente puede ser una forma útil para filtrar los no números cabo (este ejemplo es en VB.NET, pero es probable que sea similar en C#):

If Double.IsNaN(MyVariableName) Then 
    MyVariableName = 0 ' Or whatever you want to do here to "correct" the situation 
End If 

Si intenta utilizar una variable que tiene un valor NaN obtendrá el siguiente error:

Value was either too large or too small for a Decimal.

+3

Esto no detecta '1. # INF'. También necesita usar 'Double.IsInfinity (MyVariableName)' para verificar +/- infinito. – user1318499

2

Su pregunta "¿qué son?" Ya está respondida anteriormente.

En cuanto a la depuración (segunda pregunta) sin embargo, y en el desarrollo de las bibliotecas en las que desee comprobar si hay valores de entrada especiales, es posible encontrar las siguientes funciones útiles en Windows C++:

_isnan(), _isfinite (), y _fpclass()

En Linux/Unix debe encontrar isnan(), isfinite(), isnormal(), isinf(), fpclassify() útil (y es posible que necesite vincular con libm utilizando el compilador) bandera -lm).

Cuestiones relacionadas