【发布时间】:2016-02-24 16:01:27
【问题描述】:
在计算机程序的结构和解释一书中,有一个使用连续平方计算指数的递归过程。
(define (fast-expt b n)
(cond ((= n 0)
1)
((even? n)
(square (fast-expt b (/ n 2))))
(else
(* b (fast-expt b (- n 1))))))
现在在练习 1.16:
练习 1.16:设计一个迭代求幂过程的过程,该过程使用连续平方并使用对数步数, 和`fast-expt`一样。 (提示:使用观察(b(^n/2))^2 = (b(^2))^n/2,与指数
n和基数b一起保留一个附加状态变量a,并以乘积ab^n在不同状态之间保持不变的方式定义状态转换。进程开始时a取为1,由进程结束时a的值给出答案。一般来说,定义一个在状态之间保持不变的不变量的技术是思考迭代算法设计的一种强有力的方法。)
我花了一个星期,我完全不知道如何做这个迭代过程,所以我放弃并寻找解决方案。我找到的所有解决方案都是这样的:
(define (fast-expt a b n)
(cond ((= n 0)
a)
((even? n)
(fast-expt a (square b) (/ n 2)))
(else
(fast-expt (* a b) b (- n 1)))))
现在我明白了
(fast-expt a (square b) (/ n 2)))
使用书中的提示,但是当n 很奇怪时,我的大脑爆炸了。在递归过程中,我明白了原因
(* b (fast-expt b (- n 1))))))
有效。但是在迭代过程中,就变得完全不同了,
(fast-expt (* a b) b (- n 1)))))
它工作得很好,但我绝对不明白如何自己达到这个解决方案。看起来非常聪明。
有人可以解释为什么迭代解决方案是这样的吗?解决这类问题的一般思路是什么?
2021 年更新: 去年,我完全忘记了这个练习和我看到的解决方案。我尝试解决它,最后我使用练习中提供的不变量作为转换状态变量的基础自己解决了它。我使用现在接受的答案来验证我的解决方案。谢谢@Óscar López。
【问题讨论】:
-
大声笑,我花了 30 分钟才感到沮丧。你必须有惊人的毅力才能在这上面花一周时间。
-
@qiu 这取决于。平均而言,我花了一周到一个月的时间来解决本书中的一个练习。例如,我花了将近 7 个月的时间解决练习 1.11。我忍受了它,因为我几乎总是在解决它们之后学到一些东西。我给他们的时间最终总是值得的。这是一个例外,因为如果我发现一些无聊的事情,我实际上很容易分心和沮丧。
标签: loops recursion scheme sicp exponentiation