我發現了一個prime-sieve
函數,它使用Eratosthenes篩計算第一個質數。該方法是根據高德納的算法,我從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: contract violation
expected: vector?
given: #t
argument position: 1st
other arguments...:
如果我在prime-sieve
改變#T到別的東西在「給定」之後顯示。
我對矢量的瞭解不多。如果篩子沒有返回矢量,爲什麼不呢?我怎樣才能讓它返回矢量?如果它返回一個向量,爲什麼我的轉換功能不起作用?
我使用'#lang scheme'。感謝您的回答。這使得它更可讀。 :)你說在這種情況下生成一個列表比一個向量更好,但是因爲我必須查找篩子中的素數大約一百萬次以上(我只需要生成一次),所以有必要有一個數組/矢量返回。列表中的查找速度太慢。有可能返回一個向量而不是一個列表? –
只要在列表上使用'list-> vector'就足夠快了。 :-) 謝謝你的幫助! –
並注意你的篩子缺少素數2. –