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) (lower-bound y)))
	( p2 (* (lower-bound x) (upper-bound y)))
	( p3 (* (upper-bound x) (lower-bound y)))
	( p4 (* (upper-bound x) (upper-bound y))))
    (make-interval (min p1 p2 p3 p4)
		   (max p1 p2 p3 p4))))

能够发现,这里使用了4次乘法。然后取4此乘法的最小值为起点,最大值为终点。

按Ben的意思,我们能够将这4次乘法降低为两次,前提是对区间的端点进行推断。

事实上我们自己想一想大概能够明确Ben这段神奇的话。 比方,假设相乘的两个区间都是全然大于零的区间。两个区间的起点相乘肯定是4次乘法中最小的值,而两个终点相乘肯定是4次乘法中的最大的,这样我们仅仅须要计算两个起点相乘,还有就是两个终点相乘就能够了。

这样我们就能够使用2次乘法完毕工作,而不用4次。

只是,对我们程序猿来讲工作就复杂非常多了,我们须要取推断这9中情况,分别想好9种情况种选用什么作为结构的起点和终点。最后写出来的代码例如以下,巨烦琐:

(define (mul-interval x y)
  (if (> (lower-bound x) 0)
      (if (> (lower-bound y) 0)
	  (make-interval (* (lower-bound x) (lower-bound y)) (* (upper-bound x) (upper-bound y)))
	  (if (> (upper-bound y) 0)
	      (make-interval (* (upper-bound x) (lower-bound y)) (* (upper-bound x) (upper-bound y)))
	      (make-interval (* (lower-bound x) (upper-bound y)) (* (lower-bound x) (upper-bound y)))))
      (if (> (upper-bound x) 0)
	  (if (> (lower-bound y) 0)
	      (make-interval (* (lower-bound x) (upper-bound y)) (* (upper-bound x) (upper-bound y)))
	      (if (> (upper-bound y) 0)
		  (make-interval (* (lower-bound x) (lower-bound y))
				 (* (upper-bound x) (upper-bound y)))
		  (make-interval (* (lower-bound x) (lower-bound y))
				 (* (upper-bound x) (upper-bound y)))))
	  (if (> (lower-bound y) 0)
	      (make-interval (* (lower-bound x) (lower-bound y)) (* (upper-bound x) (upper-bound y)))
	      (if (> (upper-bound y) 0)
		  (make-interval (* (lower-bound x) (lower-bound y))
				 (* (upper-bound x) (upper-bound y)))
		  (make-interval (* (lower-bound x) (lower-bound y))
				 (* (upper-bound x) (upper-bound y))))) )))

有人可能会问。把原来那个如此优雅的过程写成如今这样有意思吗?一堆丑陋的推断。

这里须要理解的就是。假设系统中乘法是一个消耗非常大的操作。比方每一个乘法消耗2秒,这样我们做这个优化就有意义的,尽管我们写的代码丑非常多,麻烦非常多,只是代码执行效率就比較高了。

时间: 2024-10-15 02:06:44

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

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.12)解题总结 :区间的不同实现方式

SICP 习题 2.12 要求我们定义一个构造函数make-center-percent,它接收两个参数,分别代表中心点和一个误差百分比.我们需要通过这个构造函数产生一个区间.此外还需要定义一个选择函数percent,用来获取指定区间的误差百分比.还有就是需要实现一个center函数用于获取区间的中间点. 这里的关键就是要我们明白一个复合数据类型可能会有不同的表现形式,比如这里的区间可以用起点和终点表示,也可以使用中心点和误差表示. 从内部实现来讲,可以简单的将两种表现形式相关的数据都保存起来,

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),这两个公式不管从数学上