SICP学习笔记:求幂,用对数的算法复杂度解决fib数列

练习1.16,用来求一个数的幂,线形迭代的过程.讨论了正数和负数的情况

(define (do-expt b n) (cond ((> n 0) (fast-expt b b n)) ((= n 0) 1) (else (/ 1 (fast-expt b b (- 0 n)))) ) )
(define (even? n) (= (remainder n 2) 0))

(define (fast-expt a b n) ( cond ((= n 1) a) ((even? n) (fast-expt (* a a) b (/ n 2))) (else (fast-expt (* a a b) b (/ (- n 1) 2))) ) )

还有另外一种思路:不停的记录b的变化,如果n是奇数,就把a-〉a*b然后n->n-1,否则不停的double b的值.

(define (fast-expt b n) (expt-iter b n 1))

(define (expt-iter b n a) (cond ((= n 0) a) ((even? n) (expt-iter (square b) (/ n 2) a)) ((odd? n) (expt-iter b (- n 1) (* b a)))))

练习1.17:线型递归的加法:

(define (even? n) (= (remainder n 2) 0))
(define (halve a) (/ a 2))
(define (double a) (* a 2))
(define (fast-multi a b) ( cond ((= a 0) 0) ((even? a) (double (fast-multi (halve a) b))) (else (+ b (fast-multi (- a 1) b))) ))

练习1.18,线性迭代的加法:

(define (f a b n) ( cond((= b 0) n) ((even? b)(f (double a) (halve b) n)) (else (f a (- b 1) (+ n a)))) )
(define (fast-multi a b)(f a b 0))

基本思路和1.16如出一辙,用n来代表当前的结果.

练习1.19:

(define (fib a b p q count) (define(cmp_next_p p q)(+ (* p p) (* q q))) (define (cmp_next_q p q)(+ (* q q)(* 2 p q))) (cond((= count 0) b) ((even? count)(fib a b (cmp_next_p p q) (cmp_next_q p q) (halve count))) (else (fib (+ (* b q) (* a q) (* a p)) (+ (* b p) (* a q)) p q (- count 1))) ))

( define (f n)(fib 1 0 0 1 n))

证明:

已知对于对偶 (a,b)(a,b) ,有变换 TpqTpq 为 {ab← bq+a(p+q),← bp+aq.{a← bq+a(p+q),b← bp+aq.

那么对于 TpqTpq 的平方 (Tpq)2(Tpq)2 来说,有变换 {ab← (bp+aq)q+(bq+a(p+q))(p+q)=b(2pq+q2)+a(p2+q2+2pq+q2),← (bp+aq)p+(bq+a(p+q))q=b(p2+q2)+a(2pq+q2).{a← (bp+aq)q+(bq+a(p+q))(p+q)=b(2pq+q2)+a(p2+q2+2pq+q2),b← (bp+aq)p+(bq+a(p+q))q=b(p2+q2)+a(2pq+q2).

通过对比 TpqTpq 和 (Tpq)2(Tpq)2 ,可以得出变换 Tp′q′Tp′q′ ,其中 p′=p2+q2p′=p2+q2 并且 q′=2pq+q2q′=2pq+q2 。

你可能感兴趣的:(SICP学习笔记:求幂,用对数的算法复杂度解决fib数列)