下一个代码:
(ns clojure101.series)
(defn avg [[x y]] (/ (+ x y) 2))
(defn avg-damp
[seq]
(map avg (partition 2 seq)))
(defn avg-damp-n
[n]
(apply comp (repeat n avg-damp)))
(defn sums
[seq]
(reductions + seq))
(defn Gregory-Leibniz-n
[n]
(/ (Math/pow -1 n) (inc (* 2 n))))
(def Gregory-Leibniz-pi
(map #(* 4 (Gregory-Leibniz-n %)) (iterate inc 0)))
(println (first ((avg-damp-n 10) (sums Gregory-Leibniz-pi))))
对于n = 20,我得到“超出gc开销限制”错误。 我该如何解决这个问题?
更新:我更改了avg-damp-n功能
(defn avg-damp-n
[n seq]
(if (= n 0) seq
(recur (dec n) (avg-damp seq))))
现在我可以得到n = 20的数字
(time
(let [n 20]
(println n (first (avg-damp-n n (sums Gregory-Leibniz-pi))))))
20 3.141593197943081
"Elapsed time: 3705.821263 msecs"
更新2 我修正了一些错误,现在它运行得很好:
(ns clojure101.series)
(defn avg [[x y]] (/ (+ x y) 2))
(defn avg-damp
[seq]
(map avg (partition 2 1 seq)))
(defn avg-damp-n
[n]
(apply comp (repeat n avg-damp)))
(defn sums
[seq]
(reductions + seq))
(defn Gregory-Leibniz-n
[n]
(/ (int (Math/pow -1 n)) (inc (* 2 n))))
(def Gregory-Leibniz-pi
(map #(* 4 (Gregory-Leibniz-n %)) (range)))
; π = 3.14159265358979323846264338327950288419716939937510...
(time
(let [n 100]
(println n (double (first ((avg-damp-n n) (sums Gregory-Leibniz-pi)))))))
输出:
100 3.141592653589793
"Elapsed time: 239.253227 msecs"
答案 0 :(得分:3)
正如kotarak所说,在lazy seq上堆叠懒惰的seq似乎效率很低 关于GC。我可以在慢原子系统上重现这个问题。另见:
Error java.lang.OutOfMemoryError: GC overhead limit exceeded
对我来说,Gregory-Leibniz PI caclulation直接转换为仅使用一个懒惰序列的Clojure代码:
(defn Gregory-Leibniz-pi [n]
(->> (range n)
(map (fn [n] (/ (Math/pow -1 n) (inc (* 2 n)))))
(apply +)
(* 4)))
答案 1 :(得分:2)
首先,尝试一下有效的愚蠢解决方案:增加你的java堆空间。
;in your clojure launch script
java -Xmx2G ...other options...
程序的一部分在分区中并不是懒惰的,但更改它以使其变得懒惰(通过去除对count
的调用)仍然给出了默认堆大小的OutOfMemoryError。用平均值的减少计算平均值取代avg-damp-n的聪明度
(take (integer-exponent 2 20) seq)
仍会导致OutOfMemoryError。查看其他所有内容的来源,我没有看到任何其他看起来应该消耗堆的东西。
答案 2 :(得分:2)
user=> (defn avg
[xs & {:keys [n] :or {n 2}}]
(/ (reduce + xs) n))
#'user/avg
user=> (defn Gregory-Leibniz-n
[n]
(/ (Math/pow -1 n) (inc (+ n n))))
#'user/Gregory-Leibniz-n
user=> (->> (range)
(map #(* 4 (Gregory-Leibniz-n %)))
(reductions +)
(partition 20)
(map #(avg % :n 20))
first
println)
3.1689144018345354
这是正确的答案吗?我不知道这格雷戈里 - 莱布尼兹的递归,所以我 不确定这是否正确。
有一点我注意到:你想要太聪明了。即你的avg-damp-n
在懒惰的seq上堆叠懒惰的seq。由于您可以插入n
的任意值,
您迟早会遇到大型n
的堆栈溢出
这样的场景。如果有一个直截了当的解决方案,你应该更喜欢
它。不过,我不确定这是你的实际问题。 (正如我所说:相反
无益,它对我有用。)