SICP 习题 (2.12)解题总结 :区间的不同实现方式

SICP 习题 2.12 要求我们定义一个构造函数make-center-percent,它接收两个参数,分别代表中心点和一个误差百分比。我们需要通过这个构造函数产生一个区间。此外还需要定义一个选择函数percent,用来获取指定区间的误差百分比。还有就是需要实现一个center函数用于获取区间的中间点。

这里的关键就是要我们明白一个复合数据类型可能会有不同的表现形式,比如这里的区间可以用起点和终点表示,也可以使用中心点和误差表示。

从内部实现来讲,可以简单的将两种表现形式相关的数据都保存起来,比如我们同时记录区间的起点、终点、中心点和误差。但是这样我们就需要在数据更新时同时两种数据,比如我们获得了新的起点和终点数据,那我们就必须同时更新起点,终点,中心点和误差这些数据,而新的中心点和误差可以根据新的起点和终点计算出来。

既然都是需要转换,另一中实现思路就是只保留一种形式的数据,当获得另一种形式的数据时通过计算转换成第一种数据。

所以,在这里我们就依然采用之前的起点和终点的区间数据保存形式,当我们通过make-center-percent构建区间时就通过计算把中心点和误差百分比转换成起点和终点。

代码如下:

(define (make-center-percent center percent)
  (make-interval (- center (* center (/ percent 100))) (+ center (* center (/ percent 100)))))

这样,获取中心点的代码和书中就是一样的了,通过起点和终点相加再除于2可以得到:

(define (center i)
  (/ (+ (lower-bound i) (upper-bound i)) 2))

当我们知道一个区间的起点和终点,就可以通过计算宽度再得出误差偏移量,再把偏移量除于中心点就可以得出误差相对于中心点的百分比了。这里要注意的时书中对区间宽度的定义是起点到终点距离的一半,所以这里的区间宽度恰好是它的误差偏移量。计算误差百分比的代码如下:

(define (percent i)
  (* 100 (abs  (/ (interval-width i) (center i)))))

这样就完成了习题2.12。

时间: 2024-10-27 05:48:53

SICP 习题 (2.12)解题总结 :区间的不同实现方式的相关文章

SICP 习题 (2.30)解题总结 : Square-Tree

SICP 习题 2.30 要求我们完成一个叫square-tree的过程,其作用和之前的square过程差不多,square过程是针对简单列表的,将列表中的所有元素求平方,然后返回新的平方数列表.不过square不能对嵌套列表进行处理,如果列表中还包含列表的话会报错. 题目要求我们实现一个square-tree的过程,当输入的列表包含另一个列表时可以对嵌套的列表进行处理,生成所有列表元素的平方数. 这个和之前几道题差不多,都是对树状列表的遍历和处理.题目还要求我们用两种方式实现,一种使用map,

SICP 习题 (2.10)解题总结: 区间除法中除于零的问题

SICP 习题 2.10 要求我们处理区间除法运算中除于零的问题. 题中讲到一个专业程序员Ben Bitdiddle看了Alyssa的工作后提出了除于零的问题,大家留意一下这个叫Ben的人,后面会不断出现这个人,只要是这个人提到的事情一般是对的,他的角色定位是个计算机牛人,不过是办公室经常能看到的那种牛人,后面还有更牛的. 对于区间运算的除于零的问题,处理起来也比较简单,只需要判断除数是不是为零,除数为零就报错.对于一个区间来讲,所谓为零就是这个区间横跨0,再直接一点讲就是起点是负数,终点是正数

SICP 习题 (2.9)解题总结:区间的宽度和区间加减乘除的关系

SICP 习题 2.9 像是一个数学题,要我们证明区间的和与差的宽度是被加和被减的区间的宽度的函数,而对于乘法和除法来说不成立. 书中所谓宽度就是区间起点和终点差的一半,以我看来更像是区间宽度的一半,不管怎么样,差不多是一个意思.如果你把区间看成是一个线段的话,所谓宽度应该就是起点和终点的差,如果一定要把宽度的一半记作是宽度也无所谓的. 证明区间的和的宽度是被加区间的宽度的函数这一点是比较容易证明的,看下面的证明步骤: 如果有区间1是(a1 b1),还有区间2是(a2 b2), 那么区间1的宽度

SICP 习题 (2.16)解题总结:避免误差的区间计算系统

SICP 习题 2.16 问我们能不能设计一个没有问题的区间计算系统,可以避免习题2.14中的问题.题目还吓我们说这可能很难. 这一下就把我吓住了,你不是说很难吗,那就很难吧,我不会.呵呵

SICP 习题 (2.15)解题总结:区间误差的深入思考

SICP 习题 2.15 是接着 题目 2.14 的, 题目 2.14中提到了Alyssa设计的区间计算模块在并联电阻计算时会出现问题,这个问题是Lem发现的.接着,一个叫Eva的人也发现了这个问题,同时她还有更深入的思考. Eva觉得,如果一个公式可以写成一种形式,其中具有非准确性的变量不重复出现,那么Alyssa的系统产生的区间的限界会更紧一些. 因此,她觉得在计算并联电阻时,公式"1/(1/R1 + 1/R2)"比公式"(R1*R2)/ (R1 + R2)"要

SICP 习题 (2.11)解题总结:区间乘法的优化

SICP 习题 2.11又出现Ben这个人了,如曾经说到的,仅仅要是Ben说的一般都是对的. 来看看Ben说什么.他说:"通过监測区间的端点,有可能将mul-interval分解为9中情况,每种情况中所须要的乘法都不超过两次". 所以这个叫Ben的人建议Allysa重写mul-interval过程. 究竟是啥意思呢.我们先来看看曾经的mul-interval过程: (define (mul-interval x y) (let (( p1 (* (lower-bound x) (low

SICP 习题 (2.8) 解题总结:区间的减法

SICP 习题 2.8 需要我们完成区间运算的减法,区间运算的加法书中已经有了,代码如下: (define (add-interval x y) (make-interval (+ (lower-bound x) (lower-bound y)) (+ (upper-bound x) (upper-bound y)))) 以上代码很简单,就是计算区间的加法时将两个区间的起点相加,称为新区间的起点,然后将两个区间的终点相加,成为新区间的终点. 减法时加法的逆运算,我们看着加法的代码照猫画虎一番就可

SICP 习题 (2.13)解题总结:区间计算误差

SICP 习题 2.13 又像是一道数学证明题,和编程关系不大,不过这不能阻挡我们去完成它. 题目要求我们证明,当误差百分比很小的时候,可以使用一个简单的公式,根据被乘区间的误差去计算乘积的误差. 同时,为了简化问题,题目允许我们只计算所有数为正的情况,因为涉及到负数时,乘积的正负变化比较多样,不容易统一处理. 我看到题目后最直接的反应不是去证明它,而是通过程序去找到这个简单的公式,典型的程序员心理. 要做到这一点比较容易,我们构建一些误差百分比比较小的区间,将他们相乘,然后看看乘积的误差有什么

SICP 习题 (2.14)解题总结:区间误差导致的问题

SICP 习题 2.14 的题目要求并没有完全体现在题干中,这道题是和书中前面的内容相关的. 书中讲到,Alyssa做完了我们以前讨论的区间计算模块并发布出去了,然而,一段时间以后她接受到了来自一个叫做Lem的工程师的抱怨,这个叫做Lem的人应该是搞电路的,他用Alyssa的程序去计算两个电阻的并联电阻值,里面就使用了Alyssa设计的区间来表示一个电阻的电阻值.按照物理上的定律,并联电阻的公式是(R1*R2)/ (R1 + R2),或者使用1/(1/R1 + 1/R2),这两个公式不管从数学上