2013-10-01 42 views
1

我在Clojure中制作简单的阶乘程序。如何使阶乘更快?

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

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

它如何做得更快?如果可以以更快的方式完成。

+3

那么,对于初学者来说,如果你需要快速的东西,就不要使用Clojure。 ;-) – Sneftel

+1

尝试将“x”和“y”注释为整数。 – fjarri

+0

另外,您可能对[此帖子](http://www.learningclojure.com/2013/02/clojure-is-fast-is-clojure-still-fast.html)感兴趣,关于Clojure中的简单性能优化。 – fjarri

回答

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

这是我最喜欢的:

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

的'告诉Clojure中使用的BigInteger透明,以避免溢出。

+0

*'记录在哪里? –

+0

这里:[http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/*'](http://clojure.github.io/clojure/clojure.core-api。 HTML#clojure.core/*“) – bmaddy