【问题标题】:List of prime numbers from 2 to n (scheme)从 2 到 n 的素数列表(方案)
【发布时间】:2013-10-31 00:25:01
【问题描述】:

我正在尝试创建一个程序来构建从 2 到任何数字 n 的素数列表。当然,这需要迭代地完成,但我不完全知道我做错了什么。

(define (list-2-to-n n)
    (define (iter n result)
        (if (= n 0)
            result
        (if (< n 2)
           '()
            (if (= (remainder n 3) 0)
                (list-2-to-n (- n 1))
            (if (even? n)
                (list-2-to-n (- n 1))
                (iter (- n 1) (cons n result)))))))

    (iter n '())) 

每当测试用例通过过程时,它总是返回()

【问题讨论】:

  • 一方面,您只测试23 的除法,如果两者都不是,则将结果保留为nil。还有比这更多的错误,但这是一个开始。 This answer 与您的目标相似。

标签: list numbers scheme primes


【解决方案1】:

我做错了什么。

让我们看看。首先,您的缩进非常具有误导性。它确实应该正确反映代码的结构:

(define (list-2-to-n-0 n)       ; a global function
    (define (iter n result)     ; an internal function
        (if (= n 0)             
            result
            (if (< n 2)                        ; **else**
               '()
                (if (= (remainder n 3) 0)
                    (list-2-to-n (- n 1))
                    (if (even? n)              ; **else**
                        (list-2-to-n (- n 1))
                        (iter (- n 1) (cons n result)))))))
    (iter n '())) 

如果没有,至少你应该用一些 cmets 清楚地标记替代子句。

现在,您测试输入的数字是否能被 2 或 3 整除,并以完全相同的方式做出响应。这两种情况真的应该合二为一。另外,我们可以在这里使用cond,而不是这么多嵌套的ifs:

(define (list-2-to-n-1 n)       ; a global function 
    (define (iter n result)     ; an internal function
        (cond
            ((= n 0)  result)
            ((< n 2)  '())
            ((or (= (remainder n 2) 0) (= (remainder n 3) 0))
              (list-2-to-n (- n 1))       ; calling a global function, and
            (else                         ;   returning its result
              (iter (- n 1)               ; calling internal function, and
                    (cons n result)))))   ;   returning its result
    (iter n '())) 

在那里调用全局函数意味着重新开始整个过程​​ - 它将调用 its iter,初始累加器参数为 ()。对于n 大于0 的任何初始值,您所谓的n==0 的结果返回案例实际上是无法访问的,因为将首先遇到n &lt; 2 的案例,然后将返回()(正是观察到的行为)。

您不应该重新开始,即您应该始终调用内部函数。你应该修复你的基本情况。最后但并非最不重要的一点是,仅检查 2 或 3 的整除性是不够的,已经是 5 了。所以让我们在那里写 isPrime,稍后再实现它:

(define (list-2-to-n-1 n)       ; a global function
    (define (iter n result)     ; an internal function
        (cond
            ((< n 2)  result)
            ((not (isPrime n))
              (iter (- n 1) result))      ; calling internal function, without
            (else                         ;   altering the accumulator
              (iter (- n 1)               ; calling internal function, 
                    (cons n result)))))   ;   altering the accumulator
    (iter n '())) 

isPrime 需要尝试将n 除以 2,3,... 不需要尝试除以任何高于 2 的偶数,只要赔率就足够了。不需要尝试任何潜在的除数d,例如d * d &gt; n,因为如果n = f * d, f &lt;= df*d &lt;= d*dn &lt;= d*d

当然,尝试除以 9、15、77 之类的任何合数也是多余的 - 如果其中任何一个除以 n,那么它们的主要因数之一 3、5、7、11 也会除以它,我们会检测到他们更早。所以实际上,只尝试除以素数就足够了。为此,您需要重新构建代码,使其按升序构建素数的结果列表,并使用不大于 sqrt(k) 的前缀部分来测试每个候选 k

这称为trial division 算法。然后有一个更快的sieve of Eratosthenes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多