1.3 用高阶函数做抽象

1.3.1 过程作为参数

1.高阶过程

以过程作为参数,或者以过程作为返回值,这类能操作过程的过程称之为高阶过程

2.应用于积分

模式一:

(define (sum term a next b)(if (> a b)0(+ (term a)(sum term (next a) next b))))

计算:其中,f = x³ ,a=0;b=1

(define (integral1 f a b dx)(define (add-dx x) (+ x dx))(* (sum f (+ a (/ dx 2.0)) add-dx b)dx))(define (cube x) (* x x x))(integral1 cube 0 1 0.01)>0.24998750000000042   ;;cube在0和1间积分的精确值是1/4

此方法计算积分并不准确,是一个近似值。练习1.29会给出一个更精确的求积分的方法:辛普森规则

这种函数不能应用于其他语言,1.3.2节说明如和摆脱这种定义

1.3.2 用lambda构造过程

1. 一般形式

(lambda (<formal-parameters>) <body>)

<formal-parameters>为形式参数;<body>为过程体
lambda用于define同样的方式创建过程,此过程不与环境中任何名字相关联。

按如下方式阅读lambda表达式:

(lambda   (x)   (   +     x   4))
该过程  以x为参数  它加起    x 和 4

2.lambda的应用

1.不需要定义辅助过程
(define (pi-sum a b)(sum (lambda (x) (/ 1.0 (* x (+ x 2))))   ;;sum的定义是上面的模式一a(lambda (x) (+ x 4))b))
2.可用作组合式的运算符
((lambda (x y z) (+ x y (* z z))) 1 2 3)

3.用let创建局部变量

1. 一般形式
(let ((<var1> <exp1>)(<var2> <exp2>):(<varn> <expn>))<body>)

可以将它读作

令 <var1> 具有值 <exp1> 而且<var2> 具有值 <exp2> 而且:<varn> 具有值 <expn> :
在 <body>中
2.let表达式被解释为替代如下表达式的另一种语法形式

(对比 lambda可用作组合式的运算符 容易懂)

((lambda (<var1> ...<varn>)<body>)<exp1>:<expn>)

let表达式只是作为基础的lambda表达式的语法外衣罢了

1. 用于与注意

1).let使人能在尽可能接近其使用的地方创建局部变量约束:

(define (test x)(+ x (let ((x 6)) (- x 2))))(test 6)
>10

2).变量的值是在let之外计算的

(define (test x)(let ((x 3)(y (+ x 2)))(* x y)))(test 2)
>12

1.3.3 过程作为一般性方法

目的: 如何通过过程去直接描述这些方法

1.通过区间折半寻找方程的根

(define (average x y) (/ (+ x y) 2))  ;求两个数平均值(define (close-enough? x y) ;;两数之差的绝对值是否足够接近0.001(< (abs (- x y)) 0.001))#|检测过程|#
(define (search f neg-point pos-point)(let ((midpoint (average neg-point pos-point)))(if (close-enough? neg-point pos-point)midpoint(let ((test-value (f midpoint)))(cond ((positive? test-value)(search f neg-point midpoint))((negative? test-value)(search f midpoint pos-point))(else midpoint))))))
#|实现体:给一个函数f 以及零点所在区间的上下限|#
(define (half-interval-method f a b)(let ((a-value (f a))(b-value (f b)))(cond ((and (negative? a-value) (positive? b-value))(search f a b))((and (negative? b-value) (positive? a-value))(search f b a))(else(error "值不相符的" a b)))))   ;;;如果不符合上面要求就会报错(half-interval-method sin 2.0 4.0)
>3.1412353515625

2.找出函数的不动点

不动点: 假如函数上有一点(x y)满足函数f(x)=x 即:x=y,则称此点为该函数的不动点
找不动点的思路: 对于某个函数,通过从某个初始猜测值出发,反复的应用f 即:f(f(f(f(x))))。直到值的变化不大时,就找到了不动点。

(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))(fixed-point cos 1.0)

3. 开根号(平均阻尼技术)

(define tolerance 0.00001)(define (average x y) (/ (+ x y) 2))(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))
(define (sqrt1 x)(fixed-point (lambda (y) (average y (/ x y)))1.0))
(sqrt1 4)
>2.000000000000002

这个过程可以看作求y |-> x/y 的不动点
假如要求根号x,.那我如何让你的猜测值y变换成另一个值使变换后的值接近正确答案,而且可以反复进行。这样 :y = (1/2)(y + x/y) 。运用不动点相加再平均来逼近收敛的方法叫平均阻尼技术

1.3.4 过程作为返回值

1.过程作为返回值

(define (square x) (* x x))(define (average-damp f)(lambda (x) (average x (f x))))((average-damp square) 10)>55

这里的返回过程用到了上面我们介绍lambda的第二个性质:可用作组合式的运算符

那求平方根可写:

(define (sqrt2 x)(fixed-point (average-damp (lambda (y) (/ x y)))1.0))(sqrt2 4)

那求立方根可写:

(define (cube1 x)(fixed-point (average-damp (lambda (y) (/ x (square y))))1.0))

2. 求导:

将y = x³ 求导为 y = 3x² 。这个过程如何实现?
实现:

f`(x) = (g(x + dx) - g(x)) / dx

(define dx 0.000001)(define (deriv g)(lambda (x)(/ (- (g (+ x dx)) (g x))dx)))

3. 牛顿法(逼近)

优点: 牛顿法的收敛速度比折半法的收敛速度快得多

公式: f(x) = x - g(x)/g`(x)

证明:

设x是发f(x )=0的根,选取x0作为x的初始近似值,过点(x0 , f(x0))做曲线y = f(x) 的切线T,
T的方程为:y=f(x0) + f’(x0)(x-x0)
求出T与x轴的交点的横坐标 :x1 = x0 - f(x0)/f’(x0)
,过(x1, f(x1))做曲线y=f(x)的切线,
并求出该切线与x轴焦点的横坐标:x2 = x1 - f(x1)/f’(x1)
称x2为x* 的第二次近似值
重复上次的操作会得到x* 的近似序列。

求平方根:

(define (square x) (* x x))(define (deriv g)(lambda (x)(/ (- (g (+ x dx)) (g x))dx)))(define (newton-transform g)(lambda (x)(- x (/ (g x) ((deriv g) x)))))(define (newtons-method g guess)(fixed-point (newton-tansform g) guess))(define (sqrt3 x)(newtons-method (lambda (y) (- (square y) x))    ;;找y = y² - x的不动点1.0))(sqrt 16)
>4

练习:

练习 1.29

解:

#|求以a为下限,以b为上限,函数f的积分(很精确)|#
(define (sum2 h f a b n k)(if (> k n)0(+ (* (/ (h a b n) 3)(cond ((= k 0) (f a))((= k n) (f (+ a (* k (h a b k)))))((= (remainder k 2) 0) (* 2 (f (+ a (* k (h a b n))))))(else (* 4 (f (+ a (* k (h a b n))))))))(sum2 h f a b n (+ k 1)))))(define (cube x) (* x x x))(define (integral2 a b f)(define (h a b n) (/ (- b a) n))(sum2 h f a b 1000 0))(integral2 0 1 cube)
练习 1.30

解:

(define (next a) (+ a 1))(define (term a) (a))(define (sum term a next b)(define (iter a result)(if (> a b)result(iter (next a) (+ (term a) result))))(iter a 0))(define (cube a) (* a a a))(sum cube 1 next 10)
练习 1.31

解:
递归:

(define (product f a next b)(if (> a b)1.0(* (f a)(product f (next a) next b))))
(define (factorial a b f)(define (next a) (+ a 1))(* (product f a next b) 4))(define (f x)(cond ((= (remainder x 2) 0)(/ (+ x 2) (+ x 1)))(else(/ (+ x 1) (+ x 2)))))(factorial 1 10000 f)
>3.1417497057379635

迭代:

(define (product f a next b)(define (iter a result)(if (> a b)result(iter (next a) (* result (f a)))))(iter a 1.0))(define (factorial a b f)(define (next a) (+ a 1))(* (product f a next b) 4))(define (f x)(cond ((= (remainder x 2) 0)(/ (+ x 2) (+ x 1)))(else(/ (+ x 1) (+ x 2)))))(factorial 1 10000 f)
>3.1417497057380084
练习 1.32

解:
递归:
product:

(define (accumulate combiner null-value term a next b)(if (> a b)null-value(combiner (term a)(accumulate combiner null-value term (next a) next b))))(define (factorial a b f)(define (next a) (+ a 1))(define (combiner x y) (* x y))(* (accumulate combiner 1.0 f a next b) 4))

sum:

(define (accumulate combiner null-value term a next b)(if (> a b)null-value(combiner (term a)(accumulate combiner null-value term (next a) next b))))(define (sum term a next b)(define (next a) (+ a 1))(define (combiner x y) (+ x y))(accumulate combiner 0 term a next b))

迭代
product:

(define (accumulate combiner null-value term a next b)(define (iter a result)(if (> a b)result(iter (next a) (combiner result (term a)))))(iter a null-value))(define (factorial a b f)(define (next a) (+ a 1))(define (combiner x y) (* x y))(* (accumulate combiner 1.0 f a next b) 4))

sum

(define (accumulate combiner null-value term a next b)(define (iter a result)(if (> a b)result(iter (next a) (combiner result (term a)))))(iter a null-value))(define (sum term a next b)(define (next a) (+ a 1))(define (combiner x y) (+ x y))(accumulate combiner 0 term a next b))
练习 1.33

解:
a).

(define (filtered-accumulate filter combiner null-value term a next b)(if (> a b)null-value(combiner (if (filter a)(term a)null-value)(filtered-accumulate filter combiner null-value term (next a) next b))))(define (divisor a b f)(define (next a) (+ a 1))(define (combiner x y) (+ x y))(define (f x) x)(filtered-accumulate prime? combiner 0 f a next b))

b).

(define (filtered-accumulate filter combiner null-value term a next b)(if (> a b)null-value(combiner (if (filter a)(term a)null-value)(filtered-accumulate filter combiner null-value term (next a) next b))))(define (divisor n f)(define (next a) (+ a 1))(define (combiner x y) (* x y))     ;;;求乘积(define (f x) x)                    ;;;为了列出a到b之间每一个数(define (filter a) (= (GCD a n) 1)) ;;;此处的filter过滤出与n互素的正整数(filtered-accumulate filter combiner 0 f 0 next n)
练习 1.34

解:

(define (f g)(g 2))(define (square x) (* x x))(f square)(f (lambda (z) (* z (+ z 1))))(f f)
报错:
application: not a procedure;expected a procedure that can be applied to argumentsgiven: 2arguments...

会报错,因为f过程需要一个过程作为参数,当用f本身作为这个参数时;f过程的内部运行(g 2) 变成了
(f 2),而f过程需要的时过程参数不是常数,所以会报错。

练习 1.35

解:

(define (fixed-point f first-guess)(define (close-enough? v1 v2)(< (abs (- v1 v2)) 0.0001))(define (try guess)(let ((next (f guess)))(if (close-enough? guess next)next(try next))))(try first-guess))(define (huang)    (fixed-point (lambda (x) (+ (/ 1 x) 1)) 1.0))(huang)
练习 1.36

解:

(define (fixed-point f first-guess)(define (close-enough? v1 v2)(< (abs (- v1 v2)) 0.0001))(define (try guess)(display guess)  ;;;打印出guess的值(let ((next (f guess)))(newline)      ;;;换行(if (close-enough? guess next)next(try next))))(try first-guess))(define (han)(fixed-point (lambda (x)(/ (log 1000) (log x))) 1.1))(han)
练习 1.37

解:
方法一:

(define (cont-frac n d k)(define (iter i result)(if (> i k)result(iter (+ i 1) (/ (n i) (+ (d i) result)))))(iter 1 1.0))(cont-frac (lambda (i) 1.0)  ;;;这里用lambda定义的过程由于是用参数传入,在上面定义cont-frac的时候就相当有了个名字所以使用的时候写成(n i)(lambda (i) 1.0)11)

方法二(练习1.38建议使用版):

(define (cont-frac n d k)(define (iter i null-value)(if (> i k)null-value(/ (n i) (+ (d i) (iter (+ i 1) null-value)))))(iter 1 1.0))(cont-frac (lambda (i) 1.0)(lambda (i) 1.0)11)

当k=11时能保证得到的近似值具有十进制的4位精度。

练习 1.38

解:

(define (cont-frac n d k)(define (iter i null-value)(if (> i k)null-value(/ (n i) (+ (d i) (iter (+ i 1) null-value)))))(+ (iter 1 1.0) 2))(cont-frac (lambda (i) 1.0)(lambda (i) (cond ((= (remainder (+ i 1) 3) 0) (* 2 (/ (+ i 1) 3)))(else 1)))1000)
练习 1.39

解:

(define (tancf d x k)(define (iter i null-value)(if (> i k)null-value(/ (square x) (- (d i) (iter (+ i 1) null-value)))))(* (iter 1 1.0) x))(define (square x) (* x x))
(define (tan-cf x k)(define (d i)(- (* 2 i) 1))(tancf d x k))(tan-cf 1 10000)
练习 1.40

解:

#|求平方|#
(define (square x) (* x x))
(define dx 0.001)#|求导|#
(define (deriv g)(lambda (x)(/ (- (g (+ x dx)) (g x))dx)))#|牛顿法逼近零点|#
(define (newton-transform g)(lambda (x)(- x (/ (g x) ((deriv g) x)))))#|fixed-point 该过程产生出不动点的过程 |#
(define (fixed-point f first-guess)(define (close-enough? v1 v2)(< (abs (- v1 v2)) 0.00001))(define (try guess)(let ((next (f guess)))(if (close-enough? guess next)next(try next))))(try first-guess))#|返回这个过程|#
(define (newtons-method g guess)(fixed-point (newton-transform g) guess))(define (cubic a b c)(lambda (x) (+ (* x x x) (* a x x) (* b x) c)))
#|给a b c 赋值|#
(newtons-method (cubic 1 1 1) 1)>-1.0000000001211478
练习 1.41

解:

(define (double g)(lambda (x) (g (g x))))(define (inc x) (+ x 1))((double inc) 1)(((double (double double)) inc) 5)>3
>21
练习 1.42

解:

(define (inc x) (+ x 1))(define (square x) (* x x))(define (compose2 a b) (lambda (x)(a (b x))))((compose2 square inc) 6)
练习 1.43

解:
迭代:

(define (square x) (* x x))(define (repeated f n)(define (iter x n)(if (<= n 0)x(iter (f x) (- n 1))))(lambda (x)(iter x n)))
((repeated square 2) 5)
>625

递归:

(define (square x) (* x x))(define (repeated f n)(define (iter x n)(if (<= n 0)x(f (iter x (- n 1)))))(lambda (x)(iter x n)))
((repeated square 2) 5)
>625
练习 1.44

解:

(define dx 0.001)
(define (square x) (* x x))
(define (smooth f)(lambda (x)(/ (+ (f (- x dx)) (f x) (f (+ x dx))) 3)))(define (repeated f n)(define (iter x n)(if (<= n 0)x(f (iter x (- n 1)))))(lambda (x)(iter x n)))(define (smooth-repeated f n)(lambda (x)(((repeated smooth n) f) x)))
((smooth-repeated square 10) 5) ;;;f函数经过10次平滑后产生的过程应用到5上
>25.00000666666665

以后补下面两题

SICP第一章:构造过程抽象(1.3)相关推荐

  1. SICP学习笔记及题解---构造过程抽象(一)

    有段时间没看这本书了. 而且在做笔记的时候产生了一些疑问,觉得这样照着书做笔记没什么意义.于是乎,改变了一下做法.改成先提出疑问,记下重点,然后结合实际案例学习相关东西,最后附上题解, ok,下面就是 ...

  2. 计算机程序的构造和解释1构造过程抽象1.2过程与它们所产生的计算

    线性递归: function factorial(n){     return n==1 ? 1 : n*factorial(n-1); } 线性迭代: function factorial(n){ ...

  3. sicp第一章部分习题解答

    (begin(load "util.scm");ex 1.16 计算b的幂 (define (_expt product b n maxn)(if (= n maxn) produ ...

  4. rocketmq namesrv 第一章启动过程

    大家好,很高兴在这里跟大家分享下rocketmq源码实现,如有不对的地方欢迎指正. Namesrv顾名思义就是名称服务,是没有状态可横向扩展的服务.废话不多说了,直接贴代码.. 1,入口函数Names ...

  5. 计算机原理学习笔记——第一章 计算机的抽象和技术——2 程序的表象之下

    程序的表象之下

  6. 哈工大软件构造第一章总结

    软件构造第一章名为软件构造的多维视图和质量目标,作为整个课程的开篇,阐释了软件构造的对象是什么,以及软件系统构成的维度和指标. 1.软件构造的多维视图 第一章的第一部分内容可以由下面这幅图来概括: 那 ...

  7. 【软件构造】第三章第三节 抽象数据型(ADT)

    第三章第三节 抽象数据型(ADT) 3-1节研究了"数据类型"及其特性 ; 3-2节研究了方法和操作的"规约"及其特性:在本节中,我们将数据和操作复合起来,构成 ...

  8. 【Java开发语言 01】第一章 Java语言概述(基础常识+Java语言概述+Java程序运行机制及运行过程+Java语言环境的搭建+开发体验hello world+错误:编码GBK的不可映射字符)

    java入门-第一章Java语言概述 1基础常识 软件开发 人机交互方式 常用的DOS命令(win系统,有一些直接通过命令执行的) 2 Java语言概述 什么是计算机语言 关于面向对象和面向过程 Ja ...

  9. 哈工大软件构造第一章

    1. 软件构造过程中的多维度视图 多维度视图 在这里插入图片描述 Moment维度关注于程序在某一个时刻的表现,而Period维度更关注于程序在一段时间内的表现:     Build-time维度关注 ...

  10. 第一章 PX4-Pixhawk-程序编译过程解析

    第一章 PX4程序编译过程解析 PX4是一款软硬件开源的项目,目的在于学习和研究.其中也有比较好的编程习惯,大家不妨可以学习一下国外牛人的编程习惯.这个项目是苏黎世联邦理工大学的一个实验室搞出来的.该 ...

最新文章

  1. 【建站系列教程】3.1、cookie介绍
  2. numpy.matmul处理一维数组的 3维以上的性质
  3. Java 8 Stream Tutorial--转
  4. Linux下查看MySQL的安装路径
  5. 螺旋矩阵O(1)根据坐标求值
  6. python填充空值_python空值_python空值填充_python空值变量 - 云+社区 - 腾讯云
  7. cocoapods安装
  8. javascript --- [FormData的使用] 文件上传进度条展示 文件上传图片即使预览
  9. 正则表达式的运算符优先级
  10. 小贝拉机器人是朋友_小朋友最爱的肉松美味来啦!咸香浓郁,肉松??控一定不要错过~...
  11. Rails核心成员纷纷离职,“推手”竟是其创始人?
  12. C++第三方库管理工具vcpkg使用教程
  13. editormd支持上传视频
  14. [译] 强化学习中的好奇心与拖延症
  15. 高阶导数的运算法则 与 莱布尼茨公式
  16. 监控树莓派Raspberry Pi的CPU/GPU的温度
  17. 奇异值分解的物理意义
  18. 前端必会的 HTML+CSS 常用技巧 之 虚线的实现方式
  19. CF/TC 做题计划
  20. UE4源码阅读_骨骼模型与动画系统_Mesh

热门文章

  1. WARNING: There was an error checking the latest version of pip.
  2. jenkins 使用报ERROR: svn: E155010: The node ‘/aaa/bbb/ccc/ddd‘ was not found.
  3. 腾达f3虚拟服务器,腾达(Tenda)F3路由器用手机怎么设置?
  4. CAPM模型的应用--回归模型中的Alpha, r_f
  5. 颈部肌肉的锻炼方法?
  6. 认识即时通讯开发通信协议之MQTT
  7. 论文分享 Asymmetric Loss For Multi-Label Classification
  8. 洛谷P1308统计单词数Java题解
  9. 逆变器LCL滤波器参数设计(一)
  10. win7右下角显示此windows副本不是正版