在尝试解决 Euler Project 问题 7 时方案错误类型参数

scheme wrong-type-argument in attempted solution to Euler Project problem 7

我一直在努力解决 seventh Euler Project problem。我的程序如下所示:

(define (add-prime c)
    (define (smallest-divisor n) (find-divisor n 2))
    (define (find-divisor n test-divisor)
        (cond
            ((> (* test-divisor test-divisor) n) n)
            ((divides? test-divisor n) test-divisor)
            (else
                (find-divisor n (+ test-divisor 1)))))
    (define (divides? a b) (= (remainder b a) 0))
    (define (prime? n)
        (= n (smallest-divisor n)))
    (if (prime? (+ c 1))
        (+ c 1)
        (add-prime (+ c 1))))

(define (pv v c)
    (if (= c (vector-length v))
        v
        (begin
            (vector-set! v c
                (add-prime (vector-ref v (- c 1))))
            (pv v (+ c 1)))))

(let ((prime-vec (make-vector 10002)))
    (vector-set! prime-vec 0 2)
    (pv prime-vec 3)
    (display v))

输出如下所示:

In procedure add-prime:
In procedure +: Wrong type argument in position 1: #<unspecified>

我很困惑。 add-prime 程序本身运行正常,只是当我将它组合起来创建一个包含 10,002 个素数的向量时,它 returns 这个错误。

我认为您的代码中有错别字:

(let ((prime-vec (make-vector 10002)))
    (vector-set! prime-vec 0 2)
    (pv prime-vec 3)
    (display prime-vec)) ;; here you want to print the vector

如果我在 DrScheme 中 运行 这个程序,它会给出以下结果,这看起来有点不可思议:

#(2 0 0 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 ...)

您仅在地址 0

处初始化向量
(let ((prime-vec (make-vector 10002)))
    (vector-set! prime-vec 0 2)

然后你继续从地址 3

开始填充它
    (pv prime-vec 3)
=
    (let ((v prime-vec) (c 3))
        ....
            (vector-set! v c
                (add-prime (vector-ref v (- c 1))))
        ....
=
        ....
            (vector-set! prime-vec 3
                (add-prime (vector-ref prime-vec 2)))
        ....

但是您还没有在地址 2 处初始化向量的内容。

Racket 显然将值 0 用于未初始化的地址,但您的实现显然不是,而是那里有 #<unspecified>,导致错误。

从地址 1 而不是 3 开始填充向量,它应该可以修复错误。

附带说明一下,add-prime 实际上是 next-prime。命名很重要,好的命名可以减少认知负担。