1.30
Exercise 1.30. The sum procedure above generates a linear recursion. The procedure can be rewritten so
that the sum is performed iteratively. Show how to do this by filling in the missing expressions in the
following definition:
that the sum is performed iteratively. Show how to do this by filling in the missing expressions in the
following definition:
1.30的题目就是把一个递归方法sum改写成迭代。原来的sum方法是:
(defun sum (term a next b) (if (> a b) 0 (+ (funcall term a) (sum term (funcall next a) next b))))
变成下面这种样子:
(defun sum (term a next b) (defun iter (a result) (if <??> <??> (iter <??> <??>))) (iter <??> <??>))
当然了,你需要补齐那些问号。实现起来很简单,只需要使用result记录第n次迭代时,前面n-1次的和就可以了。
(defun sum-iter (term a next b) (defun iter (a result) (if (> a b) result (iter (funcall next a) (+ result (funcall term a))))) (iter a 0))
1.31
1.30里面实现了累加,这里需要实现连乘了。同时给出递归和非递归版本。参考前面sum的实现,别忘了把加号改成乘号,然后把默认值从0变成1:
(defun product (term a next b) (if (> a b) 1 (* (funcall term a) (product term (funcall next a) next b)))) (defun product-iter (term a next b) (defun iter (a result) (if (> a b) result (iter (funcall next a ) (* result (funcall term a))))) (iter a 1)) (product-iter #'(lambda (x) x) 1 #'(lambda (x) (+ x 1)) 3)
对于pi的运算,采用下面的公式:
使用上面的共识,我们让a=1,b等于迭代的次数,下面需要确认的就是term方法了。
我们把上面一个公式,两个两个拆开,就变成了这样:
写道
2 × 4 / (3 * 3)
4 × 6 / (5 * 5)
6 × 8 / (7 * 7)
....
4 × 6 / (5 * 5)
6 × 8 / (7 * 7)
....
对于第n行,分母是 (2n+1)的平方, 分子是 2n × 2(n+1), 所以term应该是:
(defun pi-term (x) (/ (* (* 2 x) (* 2 (+ 1 x))) (* (+ 1 (* 2 x)) (+ 1 (* 2 x)) ))) (* 4 (product #'pi-term 1 #'(lambda (x) (+ x 1)) 3)) (* 4 (product-iter #'pi-term 1 #'(lambda (x) (+ x 1)) 3))
1.32
把前面的sum、product再做一层抽象,编写一个accumulate函数,它与sum、product相比,多了两个参数:
combiner 对元素使用什么样的操作
null-value 元素使用完毕的值,所以,实现这样一个方法:(accumulate combiner null-value term a next b)
(defun accumulate (combiner null-value term a next b) (if (> a b) null-value (funcall combiner (funcall term a) (accumulate combiner null-value term (funcall next a) next b))) ) (defun accumulate-iter (combiner null-value term a next b) (defun iter (a result) (if (> a b) (print result) (iter (funcall next a) (funcall combiner a result)))) (iter a null-value))
下面轻松定义sum和product
(defun acc-sum (term a next b)
(accumulate #'+ 0 term a next b))
(defun acc-sum-iter (term a next b)
(accumulate-iter #'+ 0 term a next b))
(defun acc-product (term a next b)
(accumulate #'* 1 term a next b))
(defun acc-product-iter (term a next b)
(accumulate-iter #'* 1 term a next b))
来测试一下:
(defun next (x) (+ x 1)) (acc-sum #'(lambda (x) x) 1 #'next 10) (acc-sum-iter #'(lambda (x) x) 1 #'next 10) (acc-product #'(lambda (x) x) 1 #'next 4) (acc-product-iter #'(lambda (x) x) 1 #'next 4)