37 votes

Math.pow donne un résultat différent selon la version de Java

J'exécute le code suivant sur une Version du JDK 1.7.0_60:

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

Le résultat est: 1.1567055833133086

Je suis exactement le même code sur une Version du JDK 1.7.0.

Le résultat est: 1.1567055833133089

Je comprends que le double n'est pas infiniment précis, mais il y a un changement dans le java spec qui provoque la différence?

PS: Parce que nous utilisons un système d'héritage, Grosse Virgule n'est pas une option.

Edit: j'ai été en mesure de suivre le temps de le changer: Il a été introduit dans la Version du JDK 1.7.0_40 (par rapport à la Version 1.7.0_25).

41voto

Oli Charlesworth Points 148744

mais il y a un changement dans le java spec qui provoque la différence?

Non.* Selon la Javadoc Math.pow, une différence allant jusqu'à un ULP (de l'Unité à la Dernière Place) est autorisée. Si nous prenons un coup d'oeil à vos deux valeurs:

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

nous obtenons:

3ff281ddb6b6e675
3ff281ddb6b6e676

qui diffèrent en effet par une pratique de travail déloyale.

Ce que vous voyez est probablement dû à de légères différences dans la séquence d'instructions en virgule flottante utilisée par le JDK/JVM de mise en œuvre de ces opérations.


* Au moins, pas autant que je sache!

8voto

Marco13 Points 14743

Il n'y a pas eu de changement dans la spec, mais il y a eu quelques changements dans le hotspot optimiseur qui pourrait (!) être lié à ce.

Je l'ai dégoté ces parties de code:

(ce ne sont pas exactement les versions où ces modifications ont été introduites, j'ai juste pris eux à cause de la version de l'information que vous avez fournie).

Les changements (et ce que fait le code à tous) sont bien au-delà de ce que je peux analyser en temps raisonnable, mais peut-être que quelqu'un trouve cette référence d'intéressant ou d'utile.

5voto

user3679868 Points 538

Si vous voulez des valeurs à virgule flottante répétables entre machines virtuelles, vous pouvez utiliser le mot clé strictfp. Voir la question suivante. Quand dois-je utiliser le mot clé "strictfp" en java?

4voto

Damnum Points 258

Pour obtenir des résultats cohérents entre toutes les versions de Java, la solution consistait à utiliser StrictMath.pow() au lieu de Math.pow() .

Pour plus d’informations sur les causes possibles de cette différence, reportez-vous à cette réponse .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X