SICP学习笔记(2.1.4)

                                    SICP学习笔记(2.1.4) 
                                            周银辉

1,练习2.7

要得到答案,需注意到文中的一段话“Alyssa假设有一种称为区间的抽象对象,这种对象有两个端点,一个上界一个下界”,很明显,一个区间是由上界和下界来定义的,正如我们说平面上一个点是由其X坐标与Y坐标来定义的一样,所以,区间的定义函数便可写成:
(define (make-interval a b) (cons a b))
那么很自然的,求上界和下界的函数就如下了:
;定义上界
(define (lower-bound x)
  (car x))
;定义下界
(define (upper-bound x)
  (cdr x))

2,练习2.8

;定义区间减法
(define (sub-interval x y)
  (make-interval (- (lower-bound x) (lower-bound y))
                 (- (upper-bound x) (upper-bound y))))

3,练习2.9

我们先定义一下两倍区间宽度:
(define (width x)
  (/ (- (upper-bound x) (lower-bound x)) 2.0))

 对于区间加减法,我们要证明的是“区间和差的宽带等于宽带之和差”,我们下面以“差”为列,简单证明下,其中Lx表示区间x的下界,Ux表示区间x的上界,Wx表示区间x的宽度的两倍(之所以要两倍,是为了下面的证明书写起来方便,每个表达式都除以2写起来太繁琐了):
     (width ( sub-interval x y))
=> (w (make-interval (- Lx Ly) (-Ux Uy)))
=> 由 (width x)的定义可知,其等于上界减去下界,而上面表达式中(make-interval (- Lx Ly) (-Ux Uy))的上界为(-Ux Uy) 下界为 (- Lx Ly),所以
=> (- (- Ux Uy) (- Lx Ly)))
=> 为了方便理解,将上面的表达式写成中缀的形式
=> ( Ux - Uy ) - (Lx - Ly)
=> Ux - Uy -Lx + Ly
=> (Ux - Lx) - ( Uy - Ly)
=>根据Width的定义,所以
=> Wx - Wy
所以“差的宽度,等于宽度之差”,求和同理。 
乘除就不证明了,举个很简单的例子x=(2,4) y=(4,6),他们的积的宽度为8,而宽度之积为1.

4,练习2.10

非常简单,因为 y 的上下界要做分母,所以判断 其 是否为0:
(define (div-interval x y)
  (if (or (= 0 (upper-bound y)) (= 0 (lower-bound y)))
      (display "division by zero")
      (mul-interval x
                (make-interval (/ 1.0 (upper-bound y))
                               (/ 1.0 (lower-bound y))))))

5,练习2.11

Ben 这句神秘的话可真让程序变得无比晦涩啊:
(define (mul-interval x y)
  (let ((a (lower-bound x))
        (b (upper-bound x))
        (c (lower-bound y))
        (d (upper-bound y)))
    (cond ((< b 0)
           (cond ((< d 0)
                  (make-interval (* b d) (* a c)))
                 ((< c 0)
                  (make-interval (* a d) (* a c)))
                 (else
                  (make-interval (* a d) (* b c)))))
          ((< a 0)
           (cond ((< d 0)
                  (make-interval (* b c) (* a c)))
                 ((< c 0)
                  (let ((p1 (* a c))
                        (p2 (* a d))
                        (p3 (* b c))
                        (p4 (* b d)))
                    (make-interval (min p1 p2 p3 p4)
                                   (max p1 p2 p3 p4))))
                 (else
                  (make-interval (* a d) (* b d)))))
          (else
           (cond ((< d 0)
                  (make-interval (* b c) (* a d)))
                 ((< c 0)
                  (make-interval (* b c) (* b d)))
                 (else
                  (make-interval (* a c) (* b d))))))))

6, 练习2.12

 (define (percent c p)
  (* p (/ c 100.0)))

(define (make-center-percent c p)
  (let ((a (percent c p)))
    (make-interval (- c a) (+ c a))))

7,练习2.13

首先,我们假设 x 的误差为 deltaX,那么 x 值的变化范围为 (x ± deltaX),为了表示方便,我们用 dx 来代表 ± deltaX,那么x的值的变化范围是(x+dx),另外 x 的百分误差值就应该为 (dx / x ) * 100%

然后,我们看两个具有误差的数 x 与 y 相乘:
      ( x + dx) * ( y + dy )
=> xy + x * dy + y * dx + dx * dy
由于dx与dy很小,所以 dx*dy趋近于0,我们可以将其省略,上式变成:
=> xy + x * dy + y * dx
不难理解,上式中的( x * dy + y * dx ) 是 xy 的误差,也就是说 xy 的变化范围是 xy + ( x * dy + y * dx)
那么 xy 的百分误差  (( x * dy + y * dx)/ xy ) * 100%,  也就是 ( dy/y + dx/x ) * 100%

8,练习2.14

两种方法在数学上是对等的,但计算机的实际计算结果是不同的,代码如下:
(define (make-interval a b) (cons a b))

(define (lower-bound x)
  (car x))

(define (upper-bound x)
  (cdr x))

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

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

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

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

 (define (percent c p)
  (* p (/ c 100.0)))

(define (make-center-percent c p)
  (let ((a (percent c p)))
    (make-interval (- c a) (+ c a))))

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

(define a (make-center-percent 2 5))
(define b (make-center-percent 3 6))

(center (par1 a b))
(center (par2 a b))
 
两个中心点计算下来的结果分别是:1.2148016178736518 和 1.1999711093990755
的确存在这样的差异,比如说 (1/3)*3 在数学上是等于1的,但在实际计算过程中,比如我们保留小数点后两位的精度,那么 1/3 等于 0.33 , 再乘以3,最后结果是0.99

 9,练习2.15

感觉Eva Lu Ator说得有道理哈,比如数 a 在区间 (2,  3)之间,其误差为 ±0.5 ,  而 a^a 则在 (4,9)之间,误差值为 ±2.5

 

原文地址:https://www.cnblogs.com/zhouyinhui/p/1590041.html