双打正在污染我的BigDecimal数学

时间:2017-07-06 23:11:43

标签: clojure

我正在写一个Mandelbrot Set资源管理器。我需要尽可能多的精度,所以我可以尽可能放大。

我注意到混合doubleBigDecimal s的不幸副作用:它们“污染”了返回的类型:

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

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

我期待相反的结果。 BigDecimals,可能更精确,应该污染双打。

除了在可能与bigdec联系的每个号码上手动调用BigDecimal之外,还有一种方法可以阻止在{{1}上进行数学运算时自动降级到double s和double s?

2 个答案:

答案 0 :(得分:9)

在等式中引入double后,您可以限制可能具有的精度。一个精确到一百万个小数位的BigDecimal对你来说是没用的,如果你得到它的方式乘以只有15个左右有效数字的东西。您可以将结果提升为BigDecimal,但无论您喜欢与否,都会失去很多精确度。因此,Clojure的推广规则通过回馈double而不是高精度的BigDecimal来为你显而易见。

例如,请参阅http://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#BigDecimal-double-,了解为什么隐式或显式地将双精度转换为BigDecimal是一个坏主意。

答案 1 :(得分:3)

这实际上并不是一个错误,即使它至少看起来不对。为了更清楚地说明这会导致错误的答案如何比较这些表达式:

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

暂时你可能需要,如你所知,确保你只在程序中使用大小数。它可能仅限于IO函数,您引入的任何常量最后都需要M。为函数添加前置条件也可能有助于捕获某些情况。