我正在尝试编写一个简单的程序来查找n:th prime但我不认为我理解如何在球拍中正确引用变量。
我想要的是内部程序 sieve-iter 将素数添加到列表 primlst 中,该列表位于 sieve 的命名空间中但是我得到一个无限循环。我的猜测是 sieve-iter 中的 primlst 会导致问题。
(define (sieve n) ;; returns the n:th prime (n>0)
(let [(primlst '(2))
(cand 3)]
(define (sieve-iter i lst)
(cond ((null? lst) (and (cons i primlst) (sieve-iter (+ i 2) primlst))) ;;prime
((= (length primlst) n) (car primlst)) ;;end
((= (modulo i (car lst)) 0) (sieve-iter (+ i 2) primlst)) ;;non-prime
(#t (sieve-iter n (cdr lst))))) ;;unclear if prime
(sieve-iter cand primlst)))
任何帮助表示赞赏!
答案 0 :(得分:0)
你试图在一个函数中做太多,让prime-iter
只是担心迭代来建立素数列表。制作另一个内部函数来递减现有素数以测试新候选者。
(define (sieve n) ;; returns the n:th prime (n>0)
(define (sieve-iter i lst remaining)
(cond ;((null? lst) (and (cons i primlst) (sieve-iter (+ i 2) primlst))) ;;should never be null, we are building the list up
((<= remaining 0) (car lst)) ;;checking length every time gets expensive added a variable to the function
((sieve-prime? i lst) ;;if prime add to lst and recurse on next i
(sieve-iter (+ i 2) (cons i lst) (- remaining 1)))
(else
(sieve-iter (+ i 2) lst remaining)))) ; else try next
(define (sieve-prime? i lst)
(cond ((null? lst) #t)
((= 0 (modulo i (car lst))) #f)
(else (sieve-prime? i (cdr lst)))))
(let ((primlst '(2)) ;;you generally don't modify these,
(cand 3)) ;mostly they just bind values to name for convenience or keep from having to re-calculate the same thing more than once
(sieve-iter cand primlst (- n 1))))
你可以使用套装!修改之前的原始列表,但该过程显然不再是纯函数。
在调用筛子素数时,还有另一种低处理优化吗?过滤lst参数以删除大于i的平方根的值。