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-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)) )
那么我们进行一下简单分析,结果大体正确,而且前面的完全正确,所以我们先初步假设代码的逻辑没有问题,那么发生了什么呢,
我们仔细一想,计算机与实际的差别就在于计算机有精度上限以及大小上限,显然这里大小并未发生溢出,那么肯定就是浮点数无法表示更精确值,造成了结果有小数