Tengo una aplicación web y la búsqueda funciona con ElasticSearch.
Calculo valores fraccionarios en Java usando ScriptEngine :
ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); System.out.println("12*0.0254 = " + engine.eval("12*0.0254"));//0.30479999999999996 System.out.println("12000*0.0000254 = " + engine.eval("12000*0.0000254"));//0.3048Como se ve en la salida SOP en los comentarios, para la misma entrada, la salida se redondea de manera diferente.
En la interfaz de usuario, uso la función eval() incorporada de JavaScript y eso no coincide con la salida de Java inconsistente.
¿Cuál es la forma en Java de obtener resultados de expresión consistentes y correctos, es decir, 12 * 0.0254 siempre debe evaluarse como 0.3048 en lugar de 0.30479999999999996 ?
El hecho de que dos expresiones sean matemáticamente equivalentes no significa que evalúen el mismo valor en una aritmética de máquina determinada.
La máquina virtual de Java incorpora un subconjunto de la aritmética de coma flotante especificada en el estándar IEEE para la aritmética binaria de coma flotante (ANSI/IEEE Std. 754-1985, Nueva York).
2.8.1. Aritmética de punto flotante de máquina virtual Java e IEEE 754
Las diferencias clave entre la aritmética de punto flotante soportada por la > Máquina Virtual Java y el estándar IEEE 754 son:
Las operaciones de punto flotante de la máquina virtual de Java no lanzan >excepciones, atrapan ni señalan de otro modo las condiciones excepcionales de IEEE 754 de >operación no válida, división por cero, desbordamiento, subdesbordamiento o inexacto. La máquina virtual de Java no tiene ningún valor NaN de señalización.
La máquina virtual de Java no es compatible con las comparaciones de punto flotante de señalización IEEE 754.
Las operaciones de redondeo de la máquina virtual de Java siempre usan IEEE 754 >redondear al modo más cercano. Los resultados inexactos se redondean al valor >representable más cercano, con empates que van al valor con un bit cero menos significativo. Este es el modo predeterminado IEEE 754. Pero las instrucciones de Java Virtual Machine > que convierten valores de tipos de punto flotante en valores de > tipos integrales se redondean hacia cero. La máquina virtual de Java no proporciona ningún medio para cambiar el modo de redondeo de punto flotante.
La máquina virtual Java no es compatible con el formato extendido simple o doble extendido IEEE 754, excepto en la medida en que se pueda decir que los conjuntos de valores de exponente doble y doble extendido admiten el formato extendido simple. Los conjuntos de valores float-extended-exponent y double-extend-exponent, que pueden admitirse opcionalmente, no corresponden a los valores de los formatos extendidos IEEE 754: los formatos extendidos IEEE 754 requieren una precisión extendida, así como un rango de exponente extendido.
Fuente: https://docs.oracle.com/javase/specs/jvms/se10/html/jvms-2.html#jvms-2.8.1 .
En JavaScript obtengo el mismo resultado que tú ( https://jsfiddle.net/ , Firefox Developer Edition 97.0b5 (64 bits):
console.log(12*0.0254); console.log(12000*0.0000254); 0.30479999999999996 0.3048¿Tal vez su marco GUI aplica redondeo?
Puede formatear la salida a un cierto número de lugares decimales en Java así:
DecimalFormat df = new DecimalFormat("#.#####"); System.out.println(df.format(12*0.0254)); System.out.println(df.format(12000*0.0000254));