我使用该系列逼近PI:
该系列的功能如下所示:
(defn- pi-series [k]
(/ (if (even? (inc k)) 1 -1)
(dec (* 2 k))))
然后我的系列生成器看起来像*:
(defn pi [n]
(* 4
(loop [k 1
acc 0]
(if (= k (inc n))
acc
(recur (inc k)
(+ acc (double (pi-series k))))))))
使用值pi
运行999,999
会产生以下结果:
(time (pi 999999))
;;=> "Elapsed time: 497.686 msecs"
;;=> 3.1415936535907734
看起来很棒,但我意识到pi
可以写得更具说法性。这就是我最终得到的结果:
(defn pi-fn [n]
(* 4 (reduce +
(map #(double (pi-series %))
(range 1 (inc n))))))
结果如下:
(time (pi-fn 999999))
;;=> "Elapsed time: 4431.626 msecs"
;;=> 3.1415936535907734
注意:声明性版本需要大约4秒钟。为什么呢?
为什么声明版本要慢得多?如何更新声明版本以使其与命令式版本一样快?
答案 0 :(得分:3)
顺便说一句,您可以将交替的有限和表示为两个和的差,从而无需单独调整每个项的符号。例如,
(defn alt-sum [f n]
(- (apply + (map f (range 1 (inc n) 2)))
(apply + (map f (range 2 (inc n) 2)))))
(time (* 4 (alt-sum #(/ 1.0 (dec (+ % %))) 999999)))
; "Elapsed time: 195.244047 msecs"
;= 3.141593653590707
在我的笔记本电脑上pi
以2500毫秒的速度运行。但是,pi
和pi-fn
(任一版本)大约运行。相同的速率(比alt-sum
慢10倍)。通常情况下,pi-fn
比<{1}} 更快。你确定在第二次计时之前没有意外插入额外的9吗?反对胡安,我不认为你不止一次地迭代序列,因为这些术语是懒惰地产生的。
pi