我正在写一个Mandelbrot Set资源管理器。我需要尽可能多的精度,所以我可以尽可能放大。
我注意到混合double
和BigDecimal
s的不幸副作用:它们“污染”了返回的类型:
(type (* 1M 2))
=> java.math.BigDecimal
(type (* 1M 2.0))
=> java.lang.Double
我期待相反的结果。 BigDecimals
,可能更精确,应该污染双打。
除了在可能与bigdec
联系的每个号码上手动调用BigDecimal
之外,还有一种方法可以阻止在{{1}上进行数学运算时自动降级到double
s和double
s?
答案 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
。为函数添加前置条件也可能有助于捕获某些情况。