SICP练习1.16

在之前的学习中,我们学习了关于求幂的一系列算法;
比如求幂的递归算法,这个算法的体验和之前学习的阶乘的算法是差不多的;

一、求幂的递归算法实现
利用(expt b n)中n不断减小达到n=0时返回值为1为终止,
(if (= n 0)
    1
    (* b (expt b (- n 1))))
这样一个过程得到的代换模型如下:
(* b (* b (* b (...(* b (- n 1)))))) 此时的n为1,
这里需要理解递归的过程。

二、求幂的迭代算法实现
利用一个计数器counter和一个乘积product,
计数器的初始值为n,不断减小到0,
其间乘积product的值为b和product相乘得到的值,
当计数器的值为0时,返回此时product的值,
(define (expt b n)
	(define (expt-iter b counter product)
	  (if (= counter 0)
	      product
	      (expt-iter b
			 (- counter 1)
			 (* b product)))))

三、快速求幂的算法实现
利用了一个公式,
当n为偶数的时候,b^n=(b^(n/2))^2,
b的n次方等于b的二分之n次方的平方,
于是有以下表达示:
(if (even? n)
    (square (fast-expt b (/ n 2)))
但是在遇到n是奇数的时候,
调用一个b乘以fast-expt,再在此时的n参数处减去一个1来实现,
(define (fast-expt b n)
  (if (even? n)
      (square (fast-expt b (/ n 2)))
      (else (* b (fast-expt b (- n 1))))))

四、用迭代的方法来实现一个有快速求幂的算法实现
这就是本练习题了,
做这道题的时候读了好几遍没有读懂题,
其实一开始他就告诉我们要求,
“请定义一个过程,它能产生出一个按照迭代方式的求幂过程”
“其中使用一系列的求平方,就像fast-expt一样只用对数个步骤”
在看中文的时候有一个地方翻译有问题,
书上“一样”两个字放在了“fast-expt”的前面,照成了阅读困难,
英文为:
“Design a procedure that evolves an iterative exponentiation
process that uses successive squaring and uses a logarithmic
number of steps, as does fast-expt.”
其中提示了b^n=(b^(n/2))^2=(b^2)^(n/2)
还有一个提示是说在指数n和基数b以外,
还要有一个维持附加状态的变量a,并定义好状态的转变,
从一个状态到另一状态的转换时乘积ab^n不变。
第二个提示不好理解,应该说的时当a成为一个形参时,
在指数为单数和双数的过程中两个过程的实参不能互相影响,
要做到这一点,a也只能是一个形参(formal parameters),
而a在两种状态下都要传递实参(argument)进去,
初始的a为形参(formal parameters),
在这里也有另一个叫法“不变量(invariant quantity)”,
最后一个提示也最为关键,
“定义一个不变量,
要求它在状态之间保持不变,
这一技术是思考迭代算法设计问题时的一种非常强有力的方法。”
这句话值得细细品味,慢慢理解。
回到正题,
在fast-expt算法中有在n为双数的时候
	(square (fast-expt b (/ n 2)))
在改变成迭代算法的时候可以利用(b^(n/2))^2=(b^2)^(n/2)
	(fast-expt (square b) (/ n 2))
其理念为把b的“n/2”次方的平方,
变成了b的平方的“n/2”次方,
如此就完成了指数为双数时递归向迭代的转换;
要完成单数指数的计算,这时就要用到不变量a了,
在网上看到的思路为,
在迭代算法(fast-expt-iter)中引入如下形参(formal parameters):
index(指数)、base(底数)、a(不变量)
当指数为0时,返回值为0,
当指数为1时,返回值为a * base,
当指数为双数时,返回值为(fast-expt-iter (square base) (/ n 2) a)
当指数为单数时,且每次出现指数为单数时,
在过程中当时a这个形参的值就会是a * base,
	(else (fast-expt-iter base (- index 1) (* a base)))
最后应用过程并用实参进行取代形参如下
	(fast-expt-itxer b n 1)
尝试写代码2021年3月20日17:58

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(define fast-expt
  (lambda (b n)
    (define fast-expt-iter
      (lambda (base index a)
	(cond ((= index 0) 1)
	      ((= index 1) (* a base))
	      ((even? index)
	       (fast-expt-iter (square base)
			       (/ index 2)
			       a))
	      (else (fast-expt-iter base
				    (- index 1)
				    (* a base))))))
    (define even?
      (lambda (x)
	(= (remainder x 2) 0)))
    (define square
      (lambda (x)
	(* x x)))
    (fast-expt-iter b n 1)))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值