SICP 全笔记

Exercise 5.3. Design a machine to compute square roots using Newton’s method, as described in section 1.1.7:

(define (sqrt x)
  (define (good-enough? guess)
    (< (abs (- (square guess) x)) 0.001))
  (define (improve guess)
    (average guess (/ x guess)))
  (define (sqrt-iter guess)
    (if (good-enough? guess)
        guess
        (sqrt-iter (improve guess))))
  (sqrt-iter 1.0))

Begin by assuming that good-enough? and improve operations are available as primitives. Then show how to expand these in terms of arithmetic operations. Describe each version of the sqrt machine design by drawing a data-path diagram and writing a controller definition in the register-machine language.

把 good-enough? 和 improve 当做原子操作的时候,我们可以如下画 data-path 图:

data-path diagram
                         +---+
                         | 1 |
                         +-+-+
                           |
                           v
                         +---+      -----------------
             +---------->| g | --->( good-enough?    )
             |           +-+-+      -----------------
             |             |
  g<-t       X             v
             |      +-----------+
             |       \ improve /
             |        \---+---/
             |            |
             |            X  t<-i
             |            v
             |          +---+
             |          | t |
             |          +-+-+
             |            |
             +------------+

这个图对应的语言描述为:


(controller
    (assign (reg g) (const 1.0))
 test-g
    (test (op good-enough?) (reg g))
    (branch (label done))
    (assign (reg t) (op improve) (reg g))
    (assign (reg g) (reg t))
    (goto (label test-g))
 done)

接下面,我们要把 good-enough? 用自己的方式来实现:

data-path diagram

     +---+
     | g |
     +-+-+
       |
       v
   ----------
   \ square /
    +---+--+
        |
        v
      +---+       ----------       +---+
      | t1|-----> \   -    / <-----| x |
      +---+        +---+--+        +---+
                       v
                    +----+
                    | t2 |
                    +--+-+
                       v
                  ----------
                  \  abs   /
                   +--+---+
                      |
                      v
                    +----+
                    | t3 |
                    +-+--+
                      |
                      v
                     (<)
                      ^
                      |
                  +---+---+
                  |  0.01 |
                  +-------+

将上图的 g 与之前图中的 g 合并就可以得到最终的图了。相应的程序为:


(controller
    (assign (reg g) (const 1.0))
 test-g
    ; good-enough?
    (assign (reg t1) (op square) (reg g))
    (assign (reg t2) (op -) (reg t1) (reg x))
    (assign (reg t3) (op abs) (reg t2))
    (test (op <) (reg t3) (const 0.01))
    (branch (label done))

    (assign (reg t) (op improve) (reg g))
    (assign (reg g) (reg t))
    (goto (label test-g))
 done)

再实现 improve(图略):

(controller
    (assign (reg g) (const 1.0))
 test-g
    ; good-enough?
    (assign (reg t1) (op square) (reg g))
    (assign (reg t2) (op -) (reg t1) (reg x))
    (assign (reg t3) (op abs) (reg t2))
    (test (op <) (reg t3) (const 0.01))
    (branch (label done))
    ; improve
    (assign (reg t4) (op /) (reg x) (reg g))
    (assign (reg t) (op average) (reg g) (reg t4))

    (assign (reg g) (reg t))
    (goto (label test-g))
 done)