完成示例lazy-seq here。
(defn sieve [s]
(cons (first s)
(lazy-seq (sieve (filter #(not= 0 (mod % (first s)))
(rest s))))))
如果我尝试生成超过几千个素数,我会得到一个OutOfMemoryError。根据我的研究(但我对clojure很新),我怀疑这可能是班级“抓住头”的问题,但无法弄清楚为什么会这样或者如何补救。如何更改此函数,以便在生成大量素数时不会耗尽内存?
答案 0 :(得分:2)
您可以在不创建延迟序列的情况下使用版本。它工作得更快,更便宜:
(defn sieve* [res s]
(if (empty? s)
res
(recur (conj res (first s))
(filter #(not= 0 (mod % (first s)))
(rest s)))))
(defn sieve [n]
(sieve* [] (range 2 n)))
(sieve 10000)
=> [2 3 5 7 11 13 17 ... 9941 9949 9967 9973]
这是更高效的版本:
(defn sieve* [res n maxn]
(if (> n maxn)
res
(if (some #(= 0 (mod n %))
(take (round (sqrt (count res))) res))
(recur res (inc n) maxn)
(recur (conj res n) (inc n) maxn))))
(defn sieve [n]
(sieve* [] 2 n))
(last (sieve 1000000))
=> 999983
更新。非常快/便宜的懒人版
(defn primes-seq* [primes]
(let [last-prime (last primes)]
(cons last-prime
(lazy-seq
(primes-seq*
(conj primes
(first (let [compare-primes
(take (round (sqrt (count primes)))
primes)]
(drop-while (fn [n]
(some #(= 0 (mod n %))
compare-primes))
(iterate inc (inc last-prime)))))))))))
(def primes-seq (primes-seq* [2]))
(last (take 50000 primes-seq))
=> 611953
答案 1 :(得分:1)
给定的算法通过"记住"所有以前的素数,所以如果你继续走得足够长的话,你将要筹码。
以下效果可能效率较低,但不会耗尽内存(从4clojure解决方案改为#116):
(defn prime-seq []
(letfn [(is-prime [x]
(not (some #(= (rem x %) 0) (range 2 x))))]
(filter is-prime (range))))
(take 20 (prime-seq))
;=> (0 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61)
(nth (prime-seq) 10000)
;=> 104723