Matemáticas.pow produce resultados diferentes dependiendo de la versión de Java


Estoy ejecutando el siguiente código en una versión JDK 1.7.0_60:

System.out.println(Math.pow(1.5476348320352065, (0.3333333333333333)));

El resultado es: 1.1567055833133086

Estoy ejecutando exactamente el mismo código en una versión JDK 1.7.0.

El resultado es: 1.1567055833133089

Entiendo que double no es infinitamente preciso, pero ¿hubo un cambio en la especificación de Java que causa la diferencia?

PD: Debido a que usamos un sistema heredado, Big Decimal no es una opción.

Editar: Fui capaz de rastrear el tiempo de la cambio: Se introdujo en la versión 1.7.0_40 de JDK (en comparación con la Versión 1.7.0_25).

Author: jmiserez, 2014-08-20

4 answers

¿Pero hubo un cambio en la especificación de Java que causa la diferencia?

No.* Según los Javadocs para Math.pow, se permite una diferencia de hasta un ULP (Unidad en el Último Lugar). Si echamos un vistazo a sus dos valores:

System.out.printf("%016x\n", Double.doubleToLongBits(1.1567055833133086));
System.out.printf("%016x\n", Double.doubleToLongBits(1.1567055833133089));

Obtenemos:

3ff281ddb6b6e675
3ff281ddb6b6e676

Que de hecho difieren por un ULP.

Lo que está viendo es probablemente debido a ligeras diferencias en la secuencia de instrucciones de coma flotante utilizadas por el JDK / JVM para implementar estas operaciones.


* Al menos, no hasta donde yo sé!
 41
Author: Oliver Charlesworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-20 18:47:21

No hubo ningún cambio en la especificación, pero ha habido algunos cambios en el optimizador de hotspot que podría (!) estar relacionado con esto.

Desenterré estas partes del código:

(estas no son exactamente las versiones donde se han introducido estos cambios , solo los elegí debido a la versión información que usted proporcionó).

Los cambios (y lo que el código está haciendo en absoluto) están mucho más allá de lo que puedo analizar en un tiempo razonable, pero tal vez alguien encuentra esta referencia interesante o útil.

 8
Author: Marco13,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-21 10:14:04

Si desea valores de coma flotante repetibles entre JVM, puede usar la palabra clave strictfp, consulte la siguiente pregunta ¿Cuándo debo usar la palabra clave "strictfp" en java?

 5
Author: user3679868,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:51:15

Para producir resultados consistentes entre todas las versiones de Java, la solución era usar StrictMath.pow() en lugar de Math.pow().

Para información de antecedentes sobre lo que podría causar la diferencia, consulte esta respuesta.

 4
Author: Damnum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:30:00