SICP 1.3.3:“使用高阶过程形成抽象:过程作为返回值”

(计算机程序的结构和解释)1.3.3

我的1.3.3练习解决方案也位于Github上: https : //github.com/bolducp/SICP/tree/master/exercises/chapter_01/1.3_exercises

本节着重通过两个具体的示例来说明高阶过程的有用性: 1.)找到方程fx )= 0的根; 2.)查找功能的固定点。

来自Noun项目的Cristian Scarlat创作的F Cut小提琴
“通过半间隔方法找到方程式的根

半间隔方法是一种简单但强大的技术,可用于找到方程式f(x)= 0f(x)= 0的根,其中f为连续函数。” (第67页)

长达2页的对该方法的解释是简洁明了的内容,因此在这里我不会尝试对其进行总结。 它既演示了高阶函数的定义,又演示了如何在也处理错误情况的另一个函数中使用它。 (请参阅第67–68页)

寻找功能的固定点
如果x满足方程f(x)= x,则数字xx称为函数f的固定点。” (第68页)

本节回溯到第1.1.7节中用于查找平方根的策略,该策略还实现了递归应用函数的过程 ,直到返回值在先前返回值的确定余量内(在这种情况下,在0.00001以内) 。 此示例还演示了一种方法(称为“平均转储”),如果原始实现导致无限循环,则“使振荡围绕答案”(第70页),从而使后续猜测的间隔变小。

1.3.3练习

在每个练习题下方的灰色文本框中提供了我的解决方案。

练习1.35
证明黄金分割率(第1.2.2节)是变换x↦1+ 1 / x的不动点,并使用此事实通过不动点过程计算ϕ。
x = 1 + 1/x
x^2 = x + 1
Turn this into a quadratic equation: x^2 - x - 1 = 0
And use quadratic equation factorization to get the roots:
x = 1/2(1 - √5)
x = 1/2(1 + √5)
which shows what the golden ratio we learned in 1.2.2 (ϕ = (1 + √5) / 2 = 1.618033988)is a fixed point of the transformation x = 1 + 1/x.
We use the fixed-point function that SICP provides for us: 
(define tolerance 0.00001)

(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
and plug in the function that we're trying to find a fixed point for x = 1 + 1/x, which we can turn into the anonymous Scheme function ( lambda (x) ( + 1 ( / 1 x))), and we can choose any starting value
(fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0)
练习1.36
修改定点,以便使用换行符打印生成的近似序列并显示练习1.22中显示的图元。
然后通过找到x的固定点x(1000)/ log(x)来找到x ^ x = 1000的解。 (使用Scheme的原始对数过程,该过程计算自然对数。)比较在有平均阻尼和无平均阻尼的情况下所采取的步骤数。
(请注意,您不能以1的猜测值开始定点,因为这将导致被log(1)= 0除。)
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(newline)
(display next)
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
(define (average x y)
(/ (+ x y) 2))
(fixed-point (lambda (x) (/ (log 1000)(log x))) 1.5)

here's the solution using average dumping:
(fixed-point (lambda (x) (average x (/ (log 1000)(log x)))) 1.5)
As shown in the screen shots below, using average dumping decreased the number of iterations by about two thirds.
没有平均倾销(左)与平均倾销(右)
练习1.37
无限连续分数是以下形式的表达式:
无限连续分数
举一个例子,可以证明Ni和Di都等于1的无限连续分数扩展产生1 fraction,其中ϕ是黄金分割率(在1.2.2节中介绍)。 逼近无限连续分数的一种方法是在给定数目的项之后截断展开。 这种截断(即所谓的k项有限连续分数 )具有以下形式:
假设n和d是一个自变量的过程(返回连续分数项的Ni和Di的项索引i。定义一个过程cont-frac使得求值(cont-frac ndk)计算出k的值项有限连续分数。使用大约1 approx来检查您的程序
(cont-frac (lambda (i) 1.0)
(lambda (i) 1.0)
k)
对于k的连续值。 为了得到近似于小数点后4位的近似值,您必须使k多大?
B.如果您的cont-frac过程生成了一个递归过程,请编写一个生成迭代过程的过程。 如果它生成一个迭代过程,请编写一个生成递归过程的过程。
(define (cont-frac n d k)
(define (recursive-frac i)
(if (< i k)(/ (n i) (+ (d i) (recursive-frac(+ i 1))))
(/ (n i) (d i))))
(recursive-frac 1))
; k = 12 gives us accuracy within 0.0001 of the expected 0.61803
(cont-frac (lambda (i) 1.0)
(lambda (i) 1.0)
12)
;.6180257510729613

Part B- iterative version:
(define (cont-frac-iterative n d k)
(define (iterative-frac i acc)
(if (= i 0) acc
(iterative-frac (- i 1)(/ (n i)
(+ (d i) acc)))))
(iterative-frac k (/ (n k)(d k))))
; k = 12 gives us accuracy within 0.0001 of the expected 0.61803
(cont-frac-iterative (lambda (i) 1.0)
(lambda (i) 1.0)
11)
;.6180371352785146
练习1.38
1737年,瑞士数学家莱昂哈德·欧拉(Leonhard Euler)出版了回忆录《论分数连续性》,其中包括e-2的连续小数展开式,其中e是自然对数的底数。 在这个分数中,Ni均为1,而Di依次为1,2,1,1,4,1,1,6,1,1,8,...编写一个程序,使用练习中的cont-frac程序根据Euler展开,近似为1.37 e。
(define (cont-frac d k)
(define (recursive-frac i)
(if (< i k) (/ 1.0 (+ (d i) (recursive-frac(+ i 1))))
(/ 1.0 (d i))))
(recursive-frac 1))
(define (d i)
(if (= (remainder i 3) 2) (/ (+ i 1) 1.5)
1))
(define (euler-e k)
(+ 2.0 (cont-frac d k)))
(euler-e 10)
The tricky part here was figuring out the correct function implementation for d, such that Euler's Di pattern would be maintained. Also, rather than using my final iterative function solution and supplying d as a function to cont-frac-iterative, I refactored the recursive cont-frac implementation to use the new n and d function values directly.
练习1.39
1770年,德国数学家兰伯特(JH Lambert)发表了切线函数的连续分数表示:
其中x以弧度表示。 定义一个过程(tan-cf xk),该过程根据Lambert公式计算切线函数的近似值。 k指定要计算的项数,如练习1–37中所述。
(define (cont-frac-iterative n d k)
(define (iterative-frac i acc)
(if (= i 0) acc
(iterative-frac (- i 1)(/ (n i)
(+ (d i) acc)))))
(iterative-frac k (/ (n k)(d k))))

(define (square x) (* x x))
(define (d i) (- (* 2 i) 1))
(define (tan-cf x k)
(define (n i)
(if (> i 1) (- (square x))
x))
(cont-frac-iterative n d k))

From: https://hackernoon.com/sicp-1-3-3-formulating-abstractions-with-higher-order-procedures-procedures-as-general-methods-d78f39ad5eb7

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值