SICP帮助我理解这一点

时间:2017-12-16 17:47:05

标签: scheme sicp

以下程序找到给定数n的最小整数除数(大于1)。它通过以2开始的连续整数测试n的可除性来直接实现这一点。

(define (smallest-divisor n)
  (find-divisor n 2))
(define (find-divisor n test-divisor)
  (cond ((> (square 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))

我们可以测试一个数是否是素数如下:当且仅当n是它自己的最小除数时,n才是素数。

(define (prime? n)
  (= n (smallest-divisor n)))

find-divisor的结束测试基于以下事实:如果n不是素数,则它必须具有小于或等于n.44的除数。这意味着该算法仅需要测试1和n之间的除数。因此,将n识别为素数所需的步骤数将具有增长顺序(n)。

1 个答案:

答案 0 :(得分:2)

您的上一段被复制时出现了一些错误。它是 sqrt(n),而不是 n ,这在阅读代码时很明显。

要理解此代码,您需要阅读它,慢慢地。本书的作者专门以这种冗长的方式编写了他们的代码,以便可以用英语慢慢阅读,并且在阅读时理解。据我所知,这是他们的目标。

像这样:

(define (smallest-divisor n)
  (find-divisor n 2))

我们定义一个数字 n 的最小除数,它是找到 n 除数的结果,其起始值为 2 。所以我们不会将 1 视为数字的除数。到目前为止一切都很好。

(define (find-divisor n test-divisor)

使用起始值 test divisor 查找数字 n 的除数是由(我们知道我们从 2开始 ;因为它是一个参数,这个代码准备使用赋予它的任何值...这些值是什么?现在我们知道 2 是一种可能性;让我们坚持这个想法并重新稍后检查一下):

  (cond ((> (square test-divisor) n) n)
  1. 首先将 test divisor 的平方与 n 进行比较,如果square大于 n ,则返回<结果是em> n 。我们找到了它!

        ((divides? test-divisor n) test-divisor)
    
  2. 如果之前的测试不成功,我们接下来会尝试测试测试除数是否划分 n 。如果是,我们返回 test divisor 作为结果。我们找到了它!

        (else (find-divisor n (+ test-divisor 1)))))
    
  3. 如果之前的所有测试都失败了,我们就会遇到问题:

    • 找到一个数字 n 的除数,其值为 test divisor 但没有平移找到除数相同一个 n 的数字,起始值此测试除数值 加1


    这只是用简单的英语表示,“让我们尝试将 n 与下一个测试号码分开”。

  4. (....那么, test divisor 可能有哪些值,除了 2 ?)

    (define (divides? a b)
      (= (remainder b a) 0))
    
    你能完成它吗?