如何使阶乘更快?

时间:2013-10-01 09:02:57

标签: performance algorithm clojure

我在Clojure中制作了简单的阶乘程序。

(defn fac [x y] 
     (if (= x 1) y (recur (- x 1) (* y x)))
)

(def fact [n] (fac n 1))

如何更快地完成?如果能以更快的方式完成。

3 个答案:

答案 0 :(得分:2)

您可以在此处找到许多快速因子算法:http://www.luschny.de/math/factorial/FastFactorialFunctions.htm

如上所述,Clojure不是最好的语言。考虑使用C,C ++,ForTran。

请注意您使用的数据结构,因为因子的增长非常快。

答案 1 :(得分:2)

在您自己的fact函数(或任何其他函数)的帮助下,我们可以定义这个非常快的版本:

(def fact* (mapv fact (cons 1 (range 1 21))))

这将为常量时间范围为1到20的参数提供正确的结果。超出该范围,您的版本也没有给出正确的结果(即整数溢出(fact 21))。

编辑:这是一个改进的实现,不需要另一个fact实现,不会溢出,并且在定义期间应该快得多,因为它不会计算其查找中的每个条目从头开始:

(def fact (persistent! (reduce (fn [v n] (conj! v (*' (v n) (inc n))))
                               (transient [1])
                               (range 1000))))

编辑2 :对于不同的快速解决方案,即无需构建查找表,最好使用已经高度优化的库。 Google的通用实用程序库Guava包含一个因子实现。

通过添加此Leiningen依赖项将其添加到您的项目中:[com.google.guava/guava "15.0"]。然后,您需要(import com.google.common.math.BigIntegerMath),然后可以使用(BigIntegerMath/factorial n)调用它。

答案 2 :(得分:2)

这是我的最爱:

(defn fact [n] (reduce *' (range 1 (inc n))))

'告诉Clojure透明地使用BigInteger以避免溢出。