Performance 使用流的埃拉托斯烯球拍筛

Performance 使用流的埃拉托斯烯球拍筛,performance,stream,racket,primes,sieve-of-eratosthenes,Performance,Stream,Racket,Primes,Sieve Of Eratosthenes,当我在Racket中使用以下代码时: #lang racket (define (sieve x) (if (stream-empty? x) empty-stream (stream-cons (stream-first x) (sieve (stream-filter (λ(q)(not (zero? (modulo q (stream-first x))))) (stream-rest x))))

当我在Racket中使用以下代码时:

#lang racket
(define (sieve x)
  (if (stream-empty? x) empty-stream
      (stream-cons (stream-first x)
            (sieve (stream-filter (λ(q)(not (zero? (modulo q (stream-first x)))))
                           (stream-rest x))))))
(define (in-primes)
  (sieve (in-naturals 2)))
(define (nth-prime n)
  (for/last ([i (in-range n)]
             [j (in-primes)]) j))

我能有效计算第n个素数的最大数是1000。这是对埃拉托斯坦筛的合理实施,还是我可以做些什么来显著加快上述过程

不,不是。这是一种尝试除法算法,效率极低且次优

这里的每一个候选者都通过其前面的所有素数进行测试,而仅仅那些不大于其平方根的素数就足够了。这意味着复杂性的极大恶化。我预计它最多在~n2下运行,产生n个素数,而不是~n1.45的最优试分筛,或~n1.1的埃拉托斯坦实施的适当筛

过滤器的创建应该推迟到在候选对象中看到素数平方时,以使其成为最佳的试算除法算法


遵循“少做,多做”的原则,只需少量编辑,就可以大大提高代码的性能:不要在每一步都先调用
stream
。只需完全生成中间流,如下所示:

(定义(筛x)
(如果(流为空?x)
空流

(stream cons x;如果您正在寻找一种基于流/惰性列表的高效筛选算法,那么请不要再往下看:@Wes为什么?该算法过于复杂;还有其他方法可以做到这一点,更接近OP的代码。在基于流的代码中实现优先级队列是非常不平凡的事情。@Willence虽然t paper的末尾有一个更简单的列表版本,可能也很有用。@Wes是的,该代码是基础;尽管它使用了线性
foldr
使其性能低下,正如作者所解释的。