首页 > 代码库 > SICP 习题1.16-1.19体会

SICP 习题1.16-1.19体会

首先反思一下, 昨天做1.14的时候犯了一个严重错误,思维定式了,导致花了很多无用功。

1.14的关键是要想到2个物理意义。 一个是广度优先, 也就是只考虑问题递归树的第一层子数。那么必然有公式

F(n,m) = F(n- c1, m) + ... + F(n-cm, m) + 1   c1..cm为货币价值, m为货币树。 

利用这个公式,我们很容易用数学归纳法证明存在一个参数C1,满足F(n,m) > C1 * n的m次方。

但是,利用这个公式,我们是无法证明存在一个参数C2,满足F(n,m) < C2 * n的m次方。

根本原因是犯了数学竞赛中不等式证明的常规错误, 假设条件太宽了。

这样,就必须考虑第二个物理意义。  有第一种货币,和没第一种货币 2种集合。

基于假设,我们可以设定第一种货币的价值为1,且为最小货币。 

这样就得到了一个不同于上面广度优先的深度遍历公式。

F(n,m) = n + F(n , m -1) +F(n -1, m-1) + ...+ F(0, m- 1) 分别对应第一种货币选择 0次,1次,..., n次

由这个公式,我们是很容易证明上界的。 但要用这个公式证明下界, 则很难。


1.16-1.19主要是讲如何对数次求一个数的幂次方。

坦率的说, 书本的讲解不是那么让人容易理解。

如果我们考虑二进制, 则问题就很简单了。

假设b为5, 则2进制为 101, a的5次方则为   (1) * a 的四次方 + 0 * a的2次方 + a

那么, 问题就很明白了, 不管是迭代还是递归,干的都是一个事情, 从低位开始求b的二进制, 如果为1, 则做加法,0就无视。

每次将base平方。


这4道题, 用后面的高阶函数来看的话,本质都是一样的。他们只有算子的差别。

即F函数的n次方, 等价于将n转化为2进制, 依次求f函数的平方运算。


关于Fib数列, 书本的题目过于数学化, 我们换一个形式, 用数学工具矩阵来描述就很明白了。

列矩阵[Fn+1 Fn]  = 矩阵A * 列矩阵Fn  Fn-1]

矩阵A为  2 * 2的矩阵 [1 1 

                                1 0]

求Fib数列就转化为求A矩阵的n次方了。


个人参考解答如下:

1.16

(define (expt b n)
    (define (even? n)
(= (remainder n 2) 0))
    (define (square x) (* x x))
    (define (improve x)
(if (even? x)
   (/ x 2)
   (/ (- x 1) 2)))
    (define (fast-expt-iter b counter product)
(if (= counter 0)
   product
   (if (even? counter)
(fast-expt-iter (square b) (improve counter) product)
(fast-expt-iter (square b) (improve counter) (* product b)))))
    (fast-expt-iter b n 1.0))


1.17 

(define (mult-new a b)
    (define (even? b)
(= (remainder b 2) 0))
    (define (double x) (+ x x))
    (define (halve x)
   (/ x 2))
    (define (fast-mult-new a b)
(cond ((= b 0) 0)
     ((even? b) (double (fast-mult-new a (halve b))))
     (else (+ a (fast-mult-new a (- b 1))))))
    (fast-mult-new a b))


1.18

(define (mult-new a b)
    (define (even? b)
(= (remainder b 2) 0))
    (define (double x) (+ x x))
    (define (halve x) (/ x 2))
    (define (improve x)
(if (even? x)
   (halve x)
   (halve (- x 1))))
    (define (fast-mult-iter a counter product)
(if (= counter 0)
   product
   (if (even? counter)
(fast-mult-iter (double a) (improve counter) product)
(fast-mult-iter (double a) (improve counter) (+ product a)))))
    (fast-mult-iter a b 0.0))


1.19

p‘ = p^2 + q^2

q‘ = 2*p*q + q^2

(define (fib n)
    (define (calc-p p q)
(+ (* p p)
  (* q q)))
    (define (calc-q p q)
(+ (* 2 p q)
  (* q q)))
    (define (fib-iter a b p q count)
(cond ((= count 0) b)
     ((even? count)
      (fib-iter a
b
(calc-p p q)
(calc-q p q)
(/ count 2)))
     (else (fib-iter (+ (* b q) (* a q) (* a p))
     (+ (* b p) (* a q))
     p
     q
     (- count 1)))))
    (fib-iter 1 0 0 1 n))


SICP 习题1.16-1.19体会