2016-09-17 46 views
2

(这可能是一个愚蠢的问题,但...)如何在Clojure中获得精确的大数运算结果?

Common Lisp中,我可以这样做

CL-USER> (expt 2 63) 
9223372036854775808 

我尝试了Clojure的几个备选方案:

user> (Math/pow 2 63) 
9.223372036854776E18 

显然,强制到int没有工作:

user> (int (Math/pow 2 63)) 
IllegalArgumentException Value out of range for int: 9.223372036854776E18 clojure.lang.RT.intCast (RT.java:1211) 

所以我试图强迫到bigint

user> (bigint (Math/pow 2 63)) 
9223372036854776000N 

...但是,这也不能工作。

建议如何获得与上面相同的结果? (谢谢!)

回答

5

可以使用powBigDecimal

user=> (.pow (bigdec 2) 63) 
9223372036854775808M 

至于对付bigdec/bigint Clojure有“自动提升”计算功能,尾随'(例如*')。对于其他操作,Java interop始终是一个选项或第三方库,如https://github.com/clojure/math.numeric-tower

+1

谢谢!那么'bigdec'比'bigint'更习惯吗? (直觉上我会期望后者,因为它位于'clojure.lang'命名空间) – agam

+1

你得到一个带'bigint'的'clojure.lang/BigInt',但是'bigdec'的'java.math/BigDecimal'。您可能会发现其中一个更方便,这取决于您对JDK的暴露程度。对于一个BigInteger(JDK所具有的功能),它已经比较笨拙了:'(.pow(java.math.BigInteger。“2”)63)' – cfrick

4

Clojure使用Java数学(双精度),正如您对大多数事情所做的那样。如果您希望使用任意精度数学,你可以使用BigDecimal类编写自己的简单的功能:

(defn my-pow [x y] 
    (apply * (repeat y (bigdec x)))) 

(println (my-pow 2 63)) 

> lein run 
(my-pow 2 63) => 9223372036854775808M 
相关问题