全部学习汇总: https://github.com/GreyZhang/g_SICP

1154_SICP学习笔记_素数求解_学习

    素数是什么?素数是除了1和自身以外不能够被其他的数整除的数。因此,判断一个数是否是素数的时候,我们得看看这个数到底有多少个约数。因此,上面引入了第一个功能设计:寻找一个数的因数。

1154_SICP学习笔记_素数求解_sicp_02

    这里提出来的这个判断规则其实是很好理解的,因为找到的是最小的因子。如果这个最小因子大于平方根,肯定自乘或者与一个更大的因子相乘的结果大于原始的数字。这显然是不正确的,因此可以得出上面的结论。

1154_SICP学习笔记_素数求解_p2p_03

    与质数有关的费马小定理。

1154_SICP学习笔记_素数求解_网络协议_04

    为了实现费马测试,设计了另一个功能:求幂然后模运算。这个计算形式在之前是看过的,关键点其实是在于奇偶判断后的分而治之。

1154_SICP学习笔记_素数求解_lisp_05

    这里也说了,这个处理方式跟幂运算的例子是十分相似的。有了这个基础功能,就可以做一个费马测试的实现了。测试的方式并不是一个穷尽检测,而是说随机测试有一定的概率性。如果测试不通过,直接给出错误的结论,否则按照指定次数随机测试完。我手头也找了一本中文译本对照看,其实发现翻译的优点问题,至少是有歧义表述。按照这里的try-it来看,应该是模运算结果为a。这时候多少看出来代码的好处了,至少是没有歧义的。

1154_SICP学习笔记_素数求解_lisp_06

1154_SICP学习笔记_素数求解_sicp_07

    费马测试并不是百分百准确,但是可以从大概率上判断准确。也有判断错误的数字,这样的数字叫做迈克尔数,1亿以内只有255个。

1154_SICP学习笔记_素数求解_p2p_08

    几个练习做了一下,还以为3个都是质数。结果即前两个是,后面一个其实是可以被7整除的。

1154_SICP学习笔记_素数求解_p2p_09

    这里给出了一个程序,理解起来是很容易的。如果传入的n不是素数,那么只显示一个空行和该数字。如果是素数,那么显示出来素数的求解时间。书中给出了一个题目,使用这个过程,编写一个查找素数的过程,检查指定范围内连续奇数的素数。用你的程序找出三个大于1000的最小素数;大于10000;大于100000;大于1000000。请注意测试每个质数所需的时间。接下来,尝试做一个这样的实现。

(define (search-for-primes n x)

  (if (> x 0)

      (if (odd? n)

          (cond ((prime? n)

                 (timed-prime-test n)

                 (search-for-primes (next-odd n) (- x 1)))

                (else (search-for-primes (next-odd n) x)))

          (search-for-primes (next-odd n) x))))


(define (next-odd n)

  (if (odd? n)

      (+ 2 n)

      (+ 1 n)))

(define (odd? n)

  (= 1 (remainder n 2)))

    运行的效果如下:

1154_SICP学习笔记_素数求解_lisp_10

    这个章节耗费了比我预想多得多的时间,原本我以为只需要按照TAOCP的算法写一遍代码就过关,后面发现其实需要理解的信息还是很多的。后面的内容中应该还会有很多类似的挑战,没办法,这是魔法!