练习 1.36

首先,根据 46 页的 fixed-point 函数,修改出一个打印猜测值版的 fixed-point

;;; 36-fixed-point.scm

(define tolerance 0.000001)

(define (fixed-point f first-guess)
                
    (define (close-enough? v1 v2)
        (< (abs (- v1 v2)) tolerance))

    (define (try guess step)
        (display-info guess step)                       ; 每次进入测试时打印一次猜测
        (let ((next (f guess)))
            (if (close-enough? next guess)
                (begin                                  ; 如果猜测完成
                    (display-info next (+ 1 step))      ; 记得算上最后一次计算 next 的猜测
                    next)
                (try next (+ 1 step)))))

    (try first-guess 1))

(define (display-info guess step)
    (display "Step: ")
    (display step)
    (display " ")
    
    (display "Guess: ")
    (display guess)
    (newline))

为了在 if 形式中执行多条表达式, fixed-point 函数内部使用了 begin 形式。

函数 display-info 用于打印猜测值 guessdisplay-info 的另一个参数 step 用于进行步数计算。

除了不动点函数外,我们还需要一个平均阻尼函数(在书本 48 页定义):

;;; p48-average-damp.scm

(load "p15-average.scm")

(define (average-damp f)
    (lambda (x)
        (average x 
                 (f x))))

最后,将给定的函数映射转换成前序表达式:

;;; 36-formula.scm

(define formula 
    (lambda (x)
        (/ (log 1000) 
           (log x))))

现在,可以进行求值测试了,先来试试不带平均阻尼的计算:

1 ]=> (load "36-fixed-point.scm")

;Loading "36-fixed-point.scm"... done
;Value: display-info

1 ]=> (load "36-formula.scm")

;Loading "36-formula.scm"... done
;Value: formula

1 ]=> (fixed-point formula 2.0)
Step: 1 Guess: 2.
Step: 2 Guess: 9.965784284662087
Step: 3 Guess: 3.004472209841214
Step: 4 Guess: 6.279195757507157
Step: 5 Guess: 3.759850702401539
Step: 6 Guess: 5.215843784925895
Step: 7 Guess: 4.182207192401397
Step: 8 Guess: 4.8277650983445906
Step: 9 Guess: 4.387593384662677
Step: 10 Guess: 4.671250085763899
Step: 11 Guess: 4.481403616895052
Step: 12 Guess: 4.6053657460929
Step: 13 Guess: 4.5230849678718865
Step: 14 Guess: 4.577114682047341
Step: 15 Guess: 4.541382480151454
Step: 16 Guess: 4.564903245230833
Step: 17 Guess: 4.549372679303342
Step: 18 Guess: 4.559606491913287
Step: 19 Guess: 4.552853875788271
Step: 20 Guess: 4.557305529748263
Step: 21 Guess: 4.554369064436181
Step: 22 Guess: 4.556305311532999
Step: 23 Guess: 4.555028263573554
Step: 24 Guess: 4.555870396702851
Step: 25 Guess: 4.555315001192079
Step: 26 Guess: 4.5556812635433275
Step: 27 Guess: 4.555439715736846
Step: 28 Guess: 4.555599009998291
Step: 29 Guess: 4.555493957531389
Step: 30 Guess: 4.555563237292884
Step: 31 Guess: 4.555517548417651
Step: 32 Guess: 4.555547679306398
Step: 33 Guess: 4.555527808516254
Step: 34 Guess: 4.555540912917957
Step: 35 Guess: 4.555532270803653
Step: 36 Guess: 4.555537970114198
Step: 37 Guess: 4.555534211524127
Step: 38 Guess: 4.555536690243655
Step: 39 Guess: 4.555535055574168
Step: 40 Guess: 4.5555361336081
Step: 41 Guess: 4.555535422664798
;Value: 4.555535422664798

接着,试试使用平均阻尼(别忘了载入 48 页的 average-damp 函数):

1 ]=> (load "p48-average-damp.scm")

;Loading "p48-average-damp.scm"...
;  Loading "p15-average.scm"... done
;... done
;Value: average-damp

1 ]=> (fixed-point (average-damp formula) 2.0)
Step: 1 Guess: 2.
Step: 2 Guess: 5.9828921423310435
Step: 3 Guess: 4.922168721308343
Step: 4 Guess: 4.628224318195455
Step: 5 Guess: 4.568346513136242
Step: 6 Guess: 4.5577305909237005
Step: 7 Guess: 4.555909809045131
Step: 8 Guess: 4.555599411610624
Step: 9 Guess: 4.5555465521473675
Step: 10 Guess: 4.555537551999825
Step: 11 Guess: 4.555536019631145
Step: 12 Guess: 4.555535758730802
;Value: 4.555535758730802

对比发现,不带平均阻尼的计算使用了 41 步,另一方面,使用平均阻尼的计算只使用了 12 步,说明平均阻尼有助于计算快速收敛。

讨论

blog comments powered by Disqus