牛顿算法
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
(define (improve guess x)
(average guess (/ x guess)))
(define (average x y)
(/ (+ x y) 2))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (sqrt x)
(sqrt-iter 1.0 x))
习题1.6
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
;应用序,先求值后判断,形成递归
(sqrt-iter (improve guess x) x)))
Eva的算法,会无法停止。原因在于,MIT-Scheme(本人用的是Gambit-c),采用的是应用序求值方式。
if语句是特殊形式,而new-if是复合过程,采用应用来做替换,于是先计算子表达式,再做替换。但是子表达式中有一项是递归的,这样判断是否需要递归的操作还未执行,就开始执行递归了,于是递归就一直进行下去不能终止,直至超过scheme的递归深度限制。
习题1.7
参照: 测试方法
;num 表示初始值,test-times表示进行test-times次测试,每次测试将num平方作为新的num
;每进行一次测试,先显示num的平方,然后显示num,最后显示xysqrt对num的平方进行的开方操作
(define (sqrt-test num test-times)
(begin (display (* num num))
(newline)
(display num)
(newline)
(display (sqrt (* num num)))
(newline)
(newline)
(if (> test-times 0)
(sqrt-test (* num num) (- test-times 1))
num)))
(1).测试很小值
> (sqrt-test 0.1 5)
.010000000000000002
.1
.10032578510960607
1.0000000000000005e-4
.010000000000000002
.03230844833048122
1.0000000000000008e-8
1.0000000000000005e-4
.03125010656242753
1.0000000000000017e-16
1.0000000000000008e-8
.03125000000000106
1.0000000000000035e-32
1.0000000000000017e-16
.03125
1.0000000000000069e-64
1.0000000000000035e-32
.03125
1.0000000000000035e-32
发现当要计算的平方根小于0.1之后,所计算出的平方根都是0.03+,这是因为虽然计算的平方根相对于实际值误差很大,但是误差小于good-enough? 中设定的0.001。
(2).测试很大值
> (sqrt-test 5 5)
25
5
5.000023178253949
625
25
25.000000063076968
390625
625
625.0000000051539
152587890625
390625
390625.
23283064365386962890625
152587890625
1.52587890625e11
542101086242752217003726400434970855712890625
23283064365386962890625
*** INTERRUPTED IN ##exact-int->flonum
发现计算5的32次方时,程序计算时间过长。可能的原因是由于精度限制,计算的结果的小数位被省略,导致平方后的误差始终大于0.001,因此程序无法停止。
监视猜测值变化率的方案
(define (sqrt-iter guess pre-guess x)
(if (good-enough? guess pre-guess)
guess
(sqrt-iter (improve guess x)
guess
x)))
(define (improve guess x)
(/ (+ guess
(/ x guess))
2.0))
(define (good-enough? guess pre-guess)
(< (/ (abs (- guess pre-guess)) ;变化率
pre-guess)
0.0001))
(define (sqrt x)
(sqrt-iter 1.0 x x))
(1).测试很小值
> (sqrt-test 0.1 5)
.010000000000000002
.1
.10000000000139897
1.0000000000000005e-4
.010000000000000002
.010000000025490747
1.0000000000000008e-8
1.0000000000000005e-4
1.0000000000082468e-4
1.0000000000000017e-16
1.0000000000000008e-8
1.0000000009432513e-8
1.0000000000000035e-32
1.0000000000000017e-16
1.0000000000006089e-16
1.0000000000000069e-64
1.0000000000000035e-32
1.0000000000106228e-32
1.0000000000000035e-32
(2).测试很大值
> (sqrt-test 600 5)
360000
600
600.0000000016597
129600000000
360000
360000.0000546434
16796160000000000000000
129600000000
1.2960000000000047e11
282110990745600000000000000000000000000000000
16796160000000000000000
1.6796160000000008e22
79586611099464008843919360000000000000000000000000000000000000000000000000000000000000000
282110990745600000000000000000000000000000000
2.821109916634466e44
6334028666297327770616228694681188660989646182809600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
79586611099464008843919360000000000000000000000000000000000000000000000000000000000000000
7.958661110068303e88
79586611099464008843919360000000000000000000000000000000000000000000000000000000000000000
习题1.8
(define (cube-roots-iter guess pre-guess x)
(if (good-enough? guess pre-guess)
guess
(cube-roots-iter (improve guess x)
guess
x)))
(define (improve guess x)
(/ (+ (/ x
(* guess guess))
(* 2 guess))
3))
(define (good-enough? guess pre-guess)
(< (/ (abs (- guess pre-guess)) ;变化率
pre-guess)
0.0001))
(define (cube-roots x)
(cube-roots-iter 1.0 x x))