3 votes

Les doubles contaminent mes calculs BigDecimal

J'écris un explorateur d'ensembles de Mandelbrot. J'ai besoin d'un maximum de précision pour pouvoir zoomer le plus possible.

J'ai remarqué un effet secondaire malheureux du mélange de double et BigDecimal ils "contaminent" le type renvoyé :

(type (* 1M 2))
=> java.math.BigDecimal

(type (* 1M 2.0))
=> java.lang.Double

Je m'attendais à l'inverse. BigDecimals qui est potentiellement plus précis, devrait contaminer les doubles.

En plus d'appeler manuellement bigdec sur chaque numéro susceptible d'entrer en contact avec un BigDecimal Existe-t-il un moyen d'empêcher la rétrogradation automatique en double lorsque l'on fait des calculs sur double et BigDecimal s ?

9voto

amalloy Points 29125

Une fois que vous avez introduit un double dans l'équation, vous limitez le degré de précision possible. Un BigDecimal précis à un million de décimales près ne vous sera d'aucune utilité si la façon dont vous l'avez obtenu a consisté à le multiplier par quelque chose qui ne comporte qu'une quinzaine de chiffres significatifs. Vous pouvez transformer le résultat en BigDecimal, mais vous avez perdu une tonne de précision, que vous le vouliez ou non. Par conséquent, les règles de promotion de Clojure rendent cela évident pour vous, en vous rendant un double au lieu d'un BigDecimal de haute précision.

Voir, par exemple, http://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#BigDecimal-double- pour savoir pourquoi c'est une mauvaise idée de convertir des doubles en BigDecimals, implicitement ou explicitement.

3voto

Arthur Ulfeldt Points 45059

Il ne s'agit pas vraiment d'un bogue, même s'il semble erroné. Pour montrer plus clairement comment cela conduit à des réponses erronées, comparez ces expressions :

user>  (* 2.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001M 1.0)
2.0
user>  (* 2.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001M 1.0M)
2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010M

Pour l'instant, vous devrez probablement, comme vous le suggérez, vous assurer que vous n'utilisez que de grandes décimales dans votre programme. Il sera probablement limité aux fonctions IO et toutes les constantes que vous introduirez devront avoir le format M à l'extrémité. L'ajout de conditions préalables aux fonctions devrait également permettre de résoudre certains problèmes.

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