SICP帮我理解这个[关闭]

问题描述 投票:0回答:1

以下程序找到给定数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)。

scheme sicp
1个回答
2
投票

复制了您的最后一个段落,但有些错误。它是sqrt(n),而不是n,这在阅读代码时很明显。

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

像这样:

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

我们定义数n的最小除数是找到n的除数,其起始值为2.所以我们不会将1视为数的除数。到现在为止还挺好。

(define (find-divisor n test-divisor)

找到具有测试除数起始值的数字n的除数是通过(嗯,我们知道我们从2开始;因为它是一个参数,这个代码准备使用给它的任何值...这些是什么值?现在我们知道2是一种可能性;让我们抓住这个想法并在以后重新检查它:

  (cond ((> (square test-divisor) n) n)
  1. 首先将测试除数的平方与n进行比较,如果平方大于n,则返回n作为结果。我们找到了! ((divides? test-divisor n) test-divisor)
  2. 如果先前的测试不成功,我们接下来尝试测试测试除数是否除以n。如果是,我们返回测试除数作为结果。我们找到了! (else (find-divisor n (+ test-divisor 1)))))
  3. 如果之前的所有测试都失败了,我们就会遇到问题: 找到一个数字n的除数,其值为测试除数但没有平移,与查找数字n的除数相同,该除数为该测试除数值加1的起始值! 这只是用简单的英语表示,“让我们尝试将n与下一个测试数字分开”。

(....那么,除了2之外,测试除数可能有多少值?)

(define (divides? a b)
  (= (remainder b a) 0))

你现在可以完成吗?

© www.soinside.com 2019 - 2024. All rights reserved.