Es porque el valor flotante más cercano a 1.3 no es lo mismo que el valor doble más cercano a 1.3. Ninguno de los valores será exactamente 1.3 - que no se puede representar exactamente en una representación binaria no recurrente.
para dar una comprensión diferente de por qué sucede esto, supongamos que tenemos dos tipos decimal de coma flotante - decimal5
y decimal10
, donde el número representa el número de dígitos significativos. Ahora supongamos que intentamos asignar el valor de "un tercio" a ambos. Usted terminaría con
decimal5 oneThird = 0.33333
decimal10 oneThird = 0.3333333333
Claramente esos valores no son iguales. Es exactamente lo mismo aquí, solo con diferentes bases involucradas.
Sin embargo, si se restringen los valores con el tipo menos precisa, encontrará que son igual en este caso particular:
double d = 1.3d;
float f = 1.3f;
System.out.println((float) d == f); // Prints true
eso no es garantía de ser el caso, sin embargo. A veces, la aproximación del literal decimal a la representación doble, y luego la aproximación de ese valor a la representación flotante, termina siendo menos precisa que la aproximación decimal recta a flotante. Un ejemplo de esto es 1.0000001788139343 (gracias a stephentyrone por encontrar este ejemplo).
somewaht con mayor seguridad, se puede hacer la comparación entre dobles, pero utilizar un float
literal en la asignación original:
double d = 1.3f;
float f = 1.3f;
System.out.println(d == f); // Prints true
En este último caso, que es un poco como decir:
decimal10 oneThird = 0.3333300000
Sin embargo, como se señaló en los comentarios, es casi seguro que no debe comparar comparando valores de punto flotante con ==. Es casi nunca lo que hay que hacer, precisamente por este tipo de cosas. Por lo general, si desea comparar dos valores, hágalo con algún tipo de comparación de igualdad "difusa", verificando si los dos números son "suficientemente cercanos" para sus propósitos. Consulte la página Java Traps: double para obtener más información.
Si realmente necesita verificar la igualdad absoluta, eso generalmente indica que debe utilizar un formato numérico diferente en primer lugar; por ejemplo, para los datos financieros, probablemente debería estar usando BigDecimal
.
Muy buena explicación, aunque es posible que un valor decimal cuidadosamente diseñado para fallar la comparación '((float) decimalValueAsDouble == decimalValueAsFloat)', debido a un doble redondeo. –
@stephentyrone: Sí, sospechaba que podría serlo, aunque todavía no he encontrado ningún ejemplo. –
Lo único que me preocupa con este post es que de alguna manera le da al OP la impresión de que puede usar yes == si no entiende los comentarios. Alguien más publicó este enlace: http://firstclassthoughts.co.uk/java/traps/java_double_traps.html, que lo explica bastante bien. – Fredrik