2012-04-28 17 views
10

Ignorando qué querría hacer esto, el estándar IEEE 754 fp no define el comportamiento de los siguientes:fundición NAN flotadores a int

float h = NAN; 
printf("%x %d\n", (int)h, (int)h); 

Gives: 80000000 -2147483648 

Básicamente, independientemente de qué valor de NAN Doy , emite 80000000 (hex) o -2147483648 (dec). ¿Hay alguna razón para esto y/o es este comportamiento correcto? Si es así, ¿cómo es?

La manera en que yo estoy dando diferentes valores de NaN está aquí: How can I manually set the bit value of a float that equates to NaN?

Así que, básicamente, ¿hay casos en los que la carga útil del NaN afecta a la salida del reparto?

Gracias!

+4

+1 porque el pirateo permite una mejor comprensión –

+0

¿Para qué lo necesitas? –

Respuesta

10

El resultado de un molde de un número de coma flotante a un entero no está definida para valores no en el rango de la variable de número entero (± 1 para truncamiento).

A NaN está fuera del intervalo, por lo que el resultado es indefinido.

De hecho, la norma solo menciona la conversión de finito valores de tipos de coma flotante a tipos enteros.

+1

Dado que el comportamiento no está definido, ¿el resultado es común para este comportamiento indefinido? es decir, ¿alguien sabe de un sistema en el que obtendría un comportamiento diferente a este? La especificación 754 dice que el comportamiento de las operaciones de NaN es que la carga útil debe llevarse a cabo. – Chris

+0

No estoy al tanto de una implementación que haga lo contrario, pero no estoy familiarizado con nada más allá de un poco de gcc. gcc produce 'INT_MIN' para todas las conversiones fuera de rango a' int', que yo sepa (pero eso también es muy poco). –

+0

Estoy bastante seguro de que quiere decir * gcc en x86 *. No hay ninguna razón para suponer que el resultado debería ser el mismo en todos lados; esto es probablemente un artefacto del comportamiento de la fpu. –

1

primer lugar, un NAN es todo lo que no se considera un número flotante de acuerdo con el estándar IEEE. Entonces puede ser varias cosas. En el compilador con el que trabajo hay NAN y -NAN, por lo que no se trata de un solo valor.

En segundo lugar, cada compilador tiene su conjunto de funciones isnan para probar este caso, por lo que el programador no tiene que ocuparse de los bits él mismo. Para resumir, no creo que echar un vistazo al valor haga la diferencia. Puede ver el valor para ver su construcción IEEE, como signo, mantisa y exponente, pero, de nuevo, cada compilador tiene sus propias funciones (o mejor dicho, biblioteca) para manejarlo.

Yo tengo más que decir acerca de su prueba, sin embargo.

float h = NAN; 
printf("%x %d\n", (int)h, (int)h); 

La pieza fundida que ha hecho truca el flotador para convertirla en un int. Si desea obtener el número entero representado por el flotador, haga lo siguiente

printf("%x %d\n", *(int *)&h, *(int *)&h); 

Es decir, se toma la dirección del flotador, a continuación, se refieren a ella como un puntero a int, y, finalmente, tomar el valor int . De esta manera, se conserva la representación de bits.

7

hay una razón para este comportamiento, pero no es algo que se debe por lo general confiar.

Como observa, IEEE-754 no especifica qué sucede cuando convierte un NaN de coma flotante en un entero, excepto que debería generar una excepción de operación no válida, que su compilador probablemente ignore. El compilador de C dice que el comportamiento no está definido, lo que significa que no solo no sabe qué resultado entero obtendrá, no sabe qué hará su programa; el estándar permite que el programa aborte o obtenga resultados locos o haga cualquier cosa. Probablemente haya ejecutado este programa en un procesador Intel, y su compilador probablemente realizó la conversión usando una de las instrucciones incorporadas. Intel especifica el comportamiento de instrucciones con mucho cuidado, y el comportamiento para convertir un punto flotante NaN a un número entero de 32 bits es volver 0x80000000, independientemente de la carga útil del NaN, que es lo que observó.

Como Intel especifica el comportamiento de la instrucción, puede confiar en ella si conoce las instrucciones utilizadas. Sin embargo, dado que el compilador no le brinda tales garantías, no puede confiar en que se use esta instrucción.

+1

Puede ser cierto que los procesadores Intel conviertan NAN a int de 32 bits como '0x80000000', pero esto no lo ayudará si su NAN es un valor constante según lo determine su compilador. En tales casos, puede ver valores distintos a INT_MIN, porque la conversión se realiza en tiempo de compilación en lugar de en tiempo de ejecución, por lo que la semántica x86 de Intel nunca entra en juego. Por ejemplo, cuando GCC convierte NAN a int en tiempo de compilación, da 0. –