Scheme中基于过滤过程局部状态可变的埃氏筛实现错误排查
核心错误定位
- 递归参数传值错位:原
sieve2的loop递归分支中,调用sievehelper2时错误传入了外层固定绑定的初始全量列表,而非上一轮筛选得到的新列表,导致每轮筛选的基准序列与当前迭代节点不匹配,最终输出出现大量重复素数项。 - 冗余重复调用:原loop的双参数结构要求在进入递归前预先计算一次筛除结果,递归环节又重复计算一次完全同源的筛除结果,无实际计算价值,还进一步放大了参数错位的错误影响。
- 状态分支语法瑕疵:原
not-divisible-by的状态更新分支使用if做无返回值判断,在Racket环境中可能出现不可预期的返回值类型,影响闭包对倍数序列的跟踪稳定性。
修复说明
严格保留原有算法结构(逐轮对序列筛选、剔除指定倍数、满足当前元素平方大于n即终止流程的设计逻辑),仅做必要调整:
- 重构loop结构,取消预计算next的冗余设计,每次迭代仅对当前传入的列表执行一次
sievehelper2筛选,彻底消除重复调用问题 - 修正递归传参逻辑,将上一轮得到的筛选列表作为下一轮的输入,保证筛选流程逐轮收敛到正确结果
- 将
not-divisible-by中的状态判断分支替换为when,保证闭包的倍数跟踪状态稳定更新
修复后完整代码
(define (sieve2 n) (let ((initial-ls (makelist n))) (let loop ((current-ls initial-ls)) (let ((next-filtered (sievehelper2 current-ls n))) (if (null? next-filtered) current-ls (cons (car current-ls) (loop next-filtered))))))) (define (sievehelper2 list n) (if (> (* (car list) (car list)) n) '() (filterfunc (not-divisible-by (car list)) list))) (define filterfunc filter) (define (not-divisible-by n) (let ((m n)) (lambda (x) (let ((ret (not (= x m)))) (when (>= x m) (set! m (+ m n))) ret)))) (define (makelist n) (range 2 (+ 1 n)))
运行(sieve2 50)可得到无重复的正确素数序列'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)。
内容的提问来源于stack exchange,提问作者Will Ness
相关产品推荐
相关产品推荐

