SICP 1.06-1.08

牛顿算法

(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))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值