1.16
1.17
这道题中,我把参数名字改了一下,使得它和1.16题中的名称保持一致,其思路完全类似于乘幂的运算。
1.18
1.19
对(a,b)经行两次Tpq变换的过程如下:
(a, b)---->(bq+aq+ap, bq+aq)---->(b(q^2 + 2pq) + a(q^2 + 2pq) + a(q^2 + p^2), b(q^2+p^2) + a(q^2 + 2pq))
所以,q'= q^2+2pq,p'= (q^2 + p^2)。
1.21
直接调用smallest-divisor过程:
执行的结果显示199和1999是素数,而19999的最小因子是7(当然这里除过1)。
1.22
注意,在这里我用了在1.3.2节引入的let过程。现在,我就可以用search-for-primes过程了,例如:
可以看到,在我的机器上检查1 000附近的素数所用的时间是0(单位是微妙)。这是由于该书写于90年代,所以在本题中我把用于测试的4个数都扩大了10 000倍,即我用到的4个数分别为100 000 000、1 000 000 000、10 000 000 000、100 000 000 000。
执行结果如下:
注意,数据中的“=======”分隔符不是程序产生的,实际上程序生成的是一个newline,但是空行在博客中显示时会被省略,所以我自己添加了分隔符。从执行结果可以看出:
|------+--------+--------+-------|
|10^8 | 10^9 | 10^10 | 10^11 | => start-number
|------+--------+--------+-------|
|5 | 14 | 132 | 663 | (ms)
|5 | 13 | 133 | 549 |
|4 | 14 | 217 | 528 |
|------+--------+--------+-------|
从表中可以看出,第2列是第1列的3倍,第4列是第3列的3倍多,而(sqrt 10) = 3.16,所以从这两组数据看还比较符合预测。但是第3列与第2列的比值几乎是10,这与3.16差的太多了,我执行了好几次都是这样,为什么会有这种反常呢?(待续)。
程序在机器上的运行时间涉及很多因素,例如,当时系统的负载等,但是总体上程序的运行时间是正比于计算所需步骤的,这个也可以从前面的数据中看出。
1.23
运行1.22练习中的找12个素数的测试,得到如下数据:
得到表数据如下:
|------+--------+--------+-------|
|10^8 | 10^9 | 10^10 | 10^11 | => start-number
|------+--------+--------+-------|
|2 | 8 | 71 | 341 | (ms)
|3 | 9 | 76 | 249 |
|3 | 9 | 78 | 311 |
|------+--------+--------+-------|
对比1.22中的表,可以看出程序的运行速度接近于原来的1倍,严格来说是稍微小于1倍,之所以这样是因为程序里还有其他操作,而不完全是检查操作。