我正在学习clojure并进行clojure-koan练习。其中一个练习是implementing a factorial function。我在玩的时候注意到了:
我的递归实现似乎适用于大数字:
(defn factorial-1 [n]
(loop [n n f 1]
(if (= n 1)
f
(recur (dec n) (* f n)))))
在REPL中调用(factorial-1 1000N)
会产生一个数字:402387260077093773...
然而,当我尝试以下懒惰序列方法时:
(defn factorial-2 [n]
(reduce * 1 (range 1 (inc n))))
在REPL中调用(factorial-2 1000N)
会产生错误:
ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)
为什么看似懒惰的序列方法会导致整数溢出错误?
答案 0 :(得分:8)
尽管传递了1000N,但您实际上从未在乘法中使用任何bigint,因为您只使用该数字来确定计算的 end 。您可以在1
处开始乘法,然后乘以1
,然后乘以2
,依此类推。如果您修改factorial-2
的定义以使用bigint,则会得到预期的行为:
(defn factorial-2 [n]
(reduce * 1N (range 1 (inc n))))
答案 1 :(得分:4)
或者您只需使用*'
功能。
(defn factorial-3 [n]
(reduce *' (range 1 (inc n))))
*'
函数支持任意精度。如果数字在Long
范围内,它将返回Long
。如果范围超出长范围,它将返回BigInt
。