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))
)

那麼我們進行一下簡單分析,結果大體正確,而且前面的完全正確,所以我們先初步假設代碼的邏輯沒有問題,那麼發生了什麼呢,

我們仔細一想,計算機與實際的差別就在於計算機有精度上限以及大小上限,顯然這裏大小並未發生溢出,那麼肯定就是浮點數無法表示更精確值,造成了結果有小數

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