2.1.4 扩展训练: 区间算术

2.1.4 扩展训练: 区间算术
"Alyssa P. Hacker" 正设计一个系统来帮助人们解决工程问题.
在她的系统中她要提供的特征是操作的量有确定的精度(例如物理设备的测量参数)的能力.
当计算执行的时候,这个结果量也有确定的精度.

电气工程师们使用"Alyssa"系统计算电气的量.对于他们而言,计算两个电阻R1和R2的
并联电阻的等价值Rp的值是必须的。
使用如下的公式:
Rp=1/(1/R1+1/R2)

电阻器的制造商仅能保证电阻值在一个误差范围内。例如,如果你买了一个电阻器,标有
6.8欧姆,10%误差,你仅能被保证电阻器的电阻值在 6.8-6-0.68=6.12 和 6.8+0.68=7.48
欧姆之间。所以,如果你有一个6.8欧姆的电阻器误差10%和一个4.7欧姆5%误差的电阻器并联,
组合后的电阻值在2.58(如果两个电阻都是最小值) 和2.97(如果两个电阻都是最大值)欧姆之间。

Alyssa的想法是实现 区间算术 作为一个对区间组合的算术操作的集合,
区间是一个表示一个不确定量的可能值的范围的对象。加,减,乘,除的两个区间的结果
是一个区间,这个区间表示结果的范围。

Alyssa假定一个叫做区间的抽象对象的存在性,这个区间有两个端点,是一个下边界,一个上边界。
她也认为给出一个区间的边界,她能使用数据组装子make-interval来组装出区间。
Alyssa首先定了一个两个区间相加的程序。她认为两个下边界的和是和的最小值,两个上边界的和是和的最大值。

(define (add-interval x y)
       (make-interval (+ (lower-bound x) (lower-bound y))
                      (+ (upper-bound x) (upper-bound y))
        )
)

Alyssa通过找到边界的积的最小值和最大值,从而也计算出了两个区间的积。使用它们作为结果区间的边界。
(最小值和最大值的计算的程序是找到任意多个参数的最小值和最大值的原生程序)

(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))
       )
)

为了除两个区间,Alyssa用第一个的边界乘以第二个的边界的倒数。注意的是倒数的区间的边界是
上边界的倒数和下边界的倒数。

(define (div-interval x y)
        (mul-interval x
             (make-interval (/ 1.0 (upper-bound y))
                            (/ 1.0 (lower-bound y))
              )
         )
)

练习2.7
Alyssa的程序是不完整的。因为她没有指定区间抽象的具体实现。这是
区间的组装子的定义。

(define (make-interval a b) (cons a b))

定义选择子upper-bound和lower-bound 完成实现。

练习2.8
根据与Alyssa相似的理由,描述如何计算两个区间的减法。
定义一个相应的减法程序,叫做sub-interval.

练习2.9
一个区间的宽度是它的上边界减下边界的差值的一半。
这个宽度是被区间指定的数的不确定性的一种度量。
对一些算术操作,组合两个区间的结果的宽度仅是一个关于参数区间的宽度的函数。
然则对于组合的其它宽度,却不是一个关于参数区间的宽度的函数。请显示出
两个区间的加减法仅是参数区间的宽度的函数。给出例子说明,对乘除法是不成立的。


练习2.10
一个专家级的系统程序员,Ben Bitdiddle,看了看Alyssa,解释说,如果一个区间的间隔为0,
除以这个区间的操作是无意义的。修改Alyssa的代码,检查这种情况,
如果发生了这种情况,报告一个错误的信息。

练习2.11
在过去,Ben也明确地注释过,“通过测试区间边界的符号性,可能把mul-interval分成9种情况。
仅有一种情况要求多于两次的乘法” 根据ben的建议,重写这个程序。

调试了她的程序后,Alyssa向一个潜在的用户,演示了这个程序,这个人报怨了这个程序解决了错误的问题。
他要这个程序能够处理的数据是表示为一个中心值,加上一个误差值,例如,
他想要的区间是形如3.5+-0.15,而不是【3.35,3.65】。
Alyssa,返回办公桌,通过提供额外的组装子和选择子,修正了这个问题。

(define (make-center-width c w)
   (make-interval (- c w) (+ c w)))

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

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

不幸的是,Alyssa的大多数用户是工程师。实际的工程场景是常常度量一个很小的不确定性。
度量的是区间的宽度与区间的中间值的比例值。 工程师们常常指定在设备参数上的百分比。
正如早前给出的电阻器的规范。

练习2.12
定义一个组装子,make-center-percent 它带有一个中间值,一个百分比误差值,产生一个期望的区间。
你必须定义一个选择子percent来产生一个给定区间的百分比误差值。center选择子如上所示。

练习2.13
显示出微小百分比误差的情况下,有一个简单的公式,用因素的误差,
来计算两个区间的乘积的适合的百分比误差。通过假定所有的数都是正值,你可能简化问题。

考虑了以上的工作后,Alyssa P.Hacker 发布了她的完成的系统。几年后,
她已经忘记了这些工作后,她接到了一个用户的电话。这个人注意到并联电阻的公式
有如下的两种代数等价的写法。
R1*R2/(R1+R2)  和 1/(1/R1+1/R2)

他写了如下的两个程序,根据不同的计算公式。
(define (par1 r1 r2)
    (div-interval (mul-interval r1 r2)
                  (add-interval r1 r2)))

(define (par2 r1 r2)
   (let ((one (make-interval 1 1)))
        (div-interval one (add-interval (div-interval one r1)
                                        (div-interval one r2)
                           )
         )
  )
)

他抱怨Alyssa的程序在两种计算方式下,给出了不同的答案。这是一个很严重的问题抱怨。


练习2.14
演示Lem是正确的。用很多的表达式,测试系统的行为。制定一些区间A,B,
再使用它们计算表达式A/A和A/B.你能得到使用误差很小的区间的更多的内部信息。
检查在中间值与误差比例形式下的计算结果。


练习2.15
另一个用户Eva,也注意到了不同的区间被代数上等价的公式计算时的问题。
她说,使用Alyssa的系统计算区间的一个公式将生成严重的错误,如果在没有变量被表示成不确定的数据
这种方式被重复的话。因此,她说Par2是一个更好的程序比par1.她是对的吗?为什么?


练习2.16
总之,要解释一下。为什么等价的数学公式可能导致不同的答案。
你能提供一个区间算术的软件包,避免这个缺陷吗,或者这个任务是无法完成的。
(警告:这是一个非常有难度的问题)

猜你喜欢

转载自blog.csdn.net/gggwfn1982/article/details/81427805