我找到了一个prime-sieve
函数,它使用了Eratosthenes的Sieve来计算第一个n
素数。该方法基于Donald Knuth的算法,我从here复制了它:
; http://community.schemewiki.org/?sieve-of-eratosthenes
(define (prime-sieve n)
(let ((pvector (make-vector (+ 1 n) #t))) ; if slot k then 2k+1 is a prime
(let loop ((p 3) ; Maintains invariant p = 2j + 1
(q 4) ; Maintains invariant q = 2j + 2jj
(j 1)
(k '())
(vec pvector))
(letrec ((lp (lambda (p q j k vec)
(loop (+ 2 p)
(+ q (- (* 2 (+ 2 p)) 2))
(+ 1 j)
k
vec)))
(eradicate (lambda (q p vec)
(if (<= q n)
(begin (vector-set! vec q #f)
(eradicate (+ q p) p vec))
vec))))
(if (<= j n)
(if (eq? #t (vector-ref vec j))
(begin (lp p q j q (eradicate q p vec)))
(lp p q j k vec))
#t)))))
我想使用该函数返回一个向量,该向量可以转换为具有函数sieve-to-list
的列表:
(define (sieve-to-list s upperlimit)
(let aux ((i 2) (acc '()))
(if (> i upperlimit)
(reverse acc)
(if (= (vector-ref s i) 1)
(aux (add1 i) (cons i acc))
(aux (add1 i) acc)))))
不幸的是,我不确定第一个函数是否返回一个向量,因为(vector? (prime-sieve 1000))
返回#f。当我运行下面的代码并尝试查看前1000个素数的列表时:
(sieve-to-list (prime-sieve 1000) 1000)
我收到错误:
vector-ref:合同违规
期望:向量?
给出:#t
参数位置:第1个其他参数......:
如果我将prime-sieve
中的#t更改为“给定”后显示的其他内容。
我对矢量知之甚少。如果筛子没有返回矢量,为什么不返回矢量?如何让它返回矢量?如果它确实返回了一个向量,为什么我的转换函数不起作用呢?