2012-04-09 8 views
20

Si estoy trabajando con un double, y convertirlo en un float, ¿cómo funciona esto exactamente? ¿El valor se trunca para que encaje en un flotante? ¿O el valor se redondea de manera diferente? Lo siento si esto suena un poco de recuperación, pero estoy tratando de entender el concepto de float y double conversiones.la conversión de doble a flotar en Java

+0

http://stackoverflow.com/a/2781125/986169 – giorashc

Respuesta

19

Desde el Java Language Specification, section 5.1.3:

Una conversión primitiva estrechamiento de doble a flotar se rige por las reglas de redondeo IEEE 754 (§4.2.4). Esta conversión puede perder precisión, pero también perder rango, lo que da como resultado un cero flotante desde un doble distinto de cero y un infinito flotante desde un doble finito. Un NaN doble se convierte en un NaN flotante y un doble infinito se convierte en el infinito flotante con la misma firma.

y section 4.2.4 dice:

El lenguaje de programación Java requiere que aritmética de punto flotante se comportan como si cada operador de coma flotante redondea el resultado de coma flotante de precisión al resultado. Los resultados inexactos deben redondearse al valor representable más cercano al resultado infinitamente preciso; si los dos valores representables más cercanos están igualmente cerca, se elige el que tiene su bit cero menos significativo. Este es el modo de redondeo predeterminado del estándar IEEE 754 conocido como redondeado al más cercano.

+0

Gracias por esto. Noté que menciona el uso de IEEE 754 redondo al más cercano. ¿Hay alguna forma de especificar un modo de redondeo diferente? – Franklin

+0

@Franklin: Hay una clase ['RoundingMode'] (http://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html), pero creo que solo se aplica a' BigDecimal' y operaciones 'BigInteger', no a operaciones en primitivas. Pero no estoy 100% seguro de eso. –

+1

Java admite solo un modo de redondeo de fp: se habló de agregar hace más años (principalmente para la comunidad de HPC, es decir, también sobre el manejo de denomes, etc.), pero lamentablemente eso no fue para nada. – Voo

8

Sugeriría que los tipos de punto flotante se consideran más útilmente como representando rangos de valores. La razón de que 0.1F muestra como 0.1 en lugar de como 0.100000001490116119384765625 es que realmente representa el rango de números de 13421772.5/134.217.728-13.421.773,5/134 217 728 (es decir ,0999999977648258209228515625-0,1000000052154064178466796875); no tendría sentido para añadir dígitos adicionales que indican el número es superior a 0.100 cuando podría ser menor, ni utilizar una cadena de nueves que indican el número es inferior a 0.100 cuando podría ser mayor.

casting un doble a un flotador seleccionará el flotador cuyo rango de valores incluye el rango de dobles representados por la doble. Tenga en cuenta que si bien esta operación no es reversible, el resultado de la operación generalmente será aritméticamente correcto; el único momento en que no sería 100% aritméticamente correcto sería si uno estuviera lanzando para flotar un doble cuyo rango estaba precisamente centrado en el límite entre dos flotadores. En esa situación, el sistema seleccionaría el flotador en un lado u otro del rango del doble; si el doble de hecho representa un número en el lado equivocado del rango, la conversión resultante sería un poco inexacta.

En la práctica, la pequeña imprecisión mencionado anteriormente es casi nunca relevante, debido a que el "intervalo de valores" representado por un tipo de coma flotante es en la práctica un poco más grande que la indicada anteriormente. Realizar un cálculo (como la suma) en dos números que tienen una cierta cantidad de incertidumbre arrojará un resultado con más incertidumbre, pero el sistema no hará un seguimiento de cuánta incertidumbre existe. No obstante, a menos que uno realice docenas de operaciones en un carro flotante o miles de operaciones en un carro doble, la cantidad de incertidumbre generalmente será lo suficientemente pequeña como para no preocuparse.

Es importante tener en cuenta que lanzar un flotador a un doble es en realidad una operación mucho más peligrosa que lanzar doble para flotar, aunque Java permite el anterior implícitamente sin una advertencia, pero grazna sobre este último. Al lanzar un flotador a un doble, el sistema selecciona el doble cuyo rango está centrado alrededor del centro del rango del flotador. Esto casi siempre dará como resultado un valor cuya incertidumbre real es mucho mayor de lo que sería típico de los números de precisión doble. Por ejemplo, si uno arroja 0.1f para duplicar, el doble resultante representará un número en el rango 0.10000000149011611 a 0.10000000149011613, aunque el número que se supone que representa (una décima) es, en términos relativos, muy lejos de ese rango.

Cuestiones relacionadas