2010-11-01 9 views
5

me encontré con un resultado inesperado en la ida y vuelta de Int32.MaxValue en un System.Single:¿Por qué el CLR desborda Int32.MaxValue -> Single -> Int32, donde la JVM no lo hace?

Int32 i = Int32.MaxValue; 
Single s = i; 
Int32 c = (Int32)s; 

Debug.WriteLine(i); // 2147483647 
Debug.WriteLine(c); // -2147483648 

me di cuenta de que hay que desborda, ya Single no tiene suficientes bits en la mantisa para mantener el valor Int32, y se redondea. Cuando cambié el conv.r4 al conv.r4.ovf en el IL, se lanza un OverflowExcpetion. Justo lo suficiente ...

Sin embargo, mientras estaba investigando este problema, he recopilado este código en Java y corrió y dio la siguiente:

int i = Integer.MAX_VALUE; 
float s = (float)i; 
int c = (int)s; 

System.out.println(i); // 2147483647 
System.out.println(c); // 2147483647 

No sé mucho acerca de la JVM, pero Me pregunto cómo lo hace. Parece mucho menos sorprendente, pero ¿cómo retiene el dígito extra después de redondear a 2.14748365E9? ¿Mantiene algún tipo de representación interna y luego lo reemplaza al volver al int? ¿O simplemente redondea a Integer.MAX_VALUE para evitar el desbordamiento?

Respuesta

3

Este caso se maneja explícitamente por §5.1.3 de la Especificación del Lenguaje Java:

Una conversión estrechamiento de un número de coma flotante a una integral tipo T toma dos pasos:

  1. En el primer paso, el número de coma flotante se convierte en ya sea a largo, si T es largo, o a a int, si T es byte, corto, char, o int, como sigue:
    • Si el número de coma flotante está NaN (§4.2.3), el resultado de la primera etapa de la conversión es un int o largo 0.
    • De lo contrario, si el número de coma flotante no es un infinito, el valor de coma flotante es redondeado a un valor entero V, redondeando hacia cero con IEEE 754 modo de redondeo a cero (§4.2.3). Entonces hay dos casos:
      • Si T es larga, y este valor entero se puede representar como un largo, entonces el resultado de la primera paso es la larga valor V.
      • lo contrario, si este entero valor puede ser representado como un int, entonces el resultado de la primera etapa es el valor int V.
    • de lo contrario, uno de los dos casos siguientes deben ser verdaderas:
      • el valor debe ser demasiado pequeño (un valor negativo de gran magnitud o infinito negativo), y el resultado del primer paso es el valor representable más pequeño de tipo int o largo.
      • El valor debe ser demasiado grande (un valor positivo de gran magnitud o infinito positivo), y el resultado de la primera etapa es la más grande valor representable de tipo int o largo.
+2

Qué especificación es esto? – codekaizen

+0

Siga el enlace, Lucas ... DaveE

+0

Ah, cómo esas ediciones hacen que los comentarios parezcan tan diferentes a cuando se publicaron por primera vez. – codekaizen

Cuestiones relacionadas