2016-09-17 75 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 
相關問題