全部学习汇总: https://github.com/GreyZhang/g_SICP
素数是什么?素数是除了1和自身以外不能够被其他的数整除的数。因此,判断一个数是否是素数的时候,我们得看看这个数到底有多少个约数。因此,上面引入了第一个功能设计:寻找一个数的因数。
这里提出来的这个判断规则其实是很好理解的,因为找到的是最小的因子。如果这个最小因子大于平方根,肯定自乘或者与一个更大的因子相乘的结果大于原始的数字。这显然是不正确的,因此可以得出上面的结论。
与质数有关的费马小定理。
为了实现费马测试,设计了另一个功能:求幂然后模运算。这个计算形式在之前是看过的,关键点其实是在于奇偶判断后的分而治之。
这里也说了,这个处理方式跟幂运算的例子是十分相似的。有了这个基础功能,就可以做一个费马测试的实现了。测试的方式并不是一个穷尽检测,而是说随机测试有一定的概率性。如果测试不通过,直接给出错误的结论,否则按照指定次数随机测试完。我手头也找了一本中文译本对照看,其实发现翻译的优点问题,至少是有歧义表述。按照这里的try-it来看,应该是模运算结果为a。这时候多少看出来代码的好处了,至少是没有歧义的。
费马测试并不是百分百准确,但是可以从大概率上判断准确。也有判断错误的数字,这样的数字叫做迈克尔数,1亿以内只有255个。
几个练习做了一下,还以为3个都是质数。结果即前两个是,后面一个其实是可以被7整除的。
这里给出了一个程序,理解起来是很容易的。如果传入的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)))
运行的效果如下:
这个章节耗费了比我预想多得多的时间,原本我以为只需要按照TAOCP的算法写一遍代码就过关,后面发现其实需要理解的信息还是很多的。后面的内容中应该还会有很多类似的挑战,没办法,这是魔法!