SICP ex1-11 ex1-12 ex1-14

ex1-11

要求用迭代的方式实现fast-exp,由于给出的HINT比较详细,指出(b^n/2)^2=(B^2)^(n/2),当n为偶数,直接二分,当n为奇数,我们将一个值单独取出放到系数中来

具体代码如下:

(define (iexp b n)
	(define (reminder x y)(if (> x y) (reminder (- x y) y) x))
	(define (is-even? x) (= (reminder x 2) 0))
	(define (square x) (* x x))	
	(define (Exp x y a)
		(cond ((= y 0) a)
				((is-even? y) (Exp (square x) (/ y 2) a))
				(else (Exp x (- y 1) (* a x)))
		)
	)
	(Exp b n 1)
)

在此不再赘述


ex1-12

题目背景:要求利用加法代替乘法,实现log级的fast-exp

显然我们需要使用二分法的思想

我们首先想到a^b=a*a^(b-1)=a+a...+a(共a^b-1次加法)然后类似二分

但经过尝试我发觉没有想象之中的那样简单要二分首先我要对(a^b-1)这个值判断奇偶,之后还要进行除2的操作,实现的难度较大(如有大神务必指教)

那么我就尝试交换一下两边a^b=a^(b-1)+..+a^(b-1)(共a次)这样做的好处就是a为常数,我们可以比较轻松地进行二分操作(好像这样思考比上面那个思考更符合递归)

激动的来验证一下我们计算a^b需要已知a^(b-1)然后进行loga次运算,然后计算a^(b-1)我们需要log(a-1)直到a^1

所以我们的 时间界为 loga+log(a-1)+...+log(a-b)估算约为log(a^2),我们可以把2提到外面,所以我们的O=loga,看来这就是我们要的结果了

代码如下:

(define (add-exp b n)
	(define (reminder x n) (if (< x n) x (reminder (- x n) n)))
	(define (new-mul base count Exp addend)
		(cond  ((= Exp count) (+ base addend))
				((= (reminder Exp (+ count count)) count) (new-mul base count (- Exp count) (+ addend base))) 
				(else (new-mul (+ base base) (+ count count ) Exp addend))
		)
	)
	(if (= n 1) b  (new-mul (add-exp b (- n 1)) 1 b 0))
)


由于ex1-13在ex1-12中有解答,在此不再进行赘述

ex1-14 题目背景给出Fib(n)=(a^n-b^n) /5^(1/2) (a=(1+5^(1/2))/2 b=(1-5^(1/2))/2

要求根据这个设计对数限的计算程序,并解释为何不合适除非n较小

以下先给出代码:(这个由于之前实现了fast-exp所以非常容易实现)


以下是一些测试结果,显然到了10就出现了问题

(define (fast-exp b n )
	(define (square x)(* x x))
	(define (is-even? x) (= (reminder n 2) 0))
	(define (reminder x n) (if (> x n) (reminder (- x n) n) x))
	(cond ((= n 0 ) 1)
			((is-even? n) (fast-exp b (/ n 2)))
			(else (* b (fast-exp b (- n 1)))))
)
(define (Fib n)
	(define a (/ (+ 1 (sqrt 5 ) ) 2))
	(define b (/ (- 1 (sqrt 5 ) ) 2))
	(/ (- (fast-exp a n) (fast-exp b n ) ) (sqrt 5))
)

那么我们进行一下简单分析,结果大体正确,而且前面的完全正确,所以我们先初步假设代码的逻辑没有问题,那么发生了什么呢,

我们仔细一想,计算机与实际的差别就在于计算机有精度上限以及大小上限,显然这里大小并未发生溢出,那么肯定就是浮点数无法表示更精确值,造成了结果有小数

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章