Skip to content

2.14

; After considerable work, Alyssa P. Hacker delivers her finished 
; system. Several years later, after she has forgotten all about 
; it, she gets a frenzied call from an irate user, Lem E. Tweakit. 
; It seems that Lem has noticed that the formula for parallel 
; resistors can be written in two algebraically equivalent ways:
;              R1R2 / (R1 + R2)
; and
;            1 / ((1/R1) + (1/R2))
; He has written the following two programs, each of which computes 
; the parallel-resistors formula differently:
(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)))))

; Lem complains that Alyssa’s program gives different answers for 
; the two ways of computing. This is a serious complaint.
; Demonstrate that Lem is right. Investigate the behavior of the 
; system on a variety of arithmetic expressions. Make some intervals 
; A and B, and use them in computing the expressions A/A and A/B. 
; You will get the most insight by using intervals whose width is a 
; small percentage of the center value. Examine the results of the 
; computation in center-percent form (see Exercise 2.12).

; Answer
; --------------------------------------

; Let's get the helpers
(define (make-interval a b)
    (cons (min a b) (max a b)))
(define (lower-bound z) (car z))
(define (upper-bound z) (cdr z))
(define (make-center-percent c p)
    (make-center-width c (/ (* c p) 100)))
(define (make-center-width c w) 
    (make-interval (- c w) (+ c w)))
(define (center i)
    (/ (+ (lower-bound i) (upper-bound i)) 2))
(define (width i)
    (/ (- (upper-bound i) (lower-bound i)) 2))
(define (percent i)
    (* (/ (width i) (center i)) 100.0))
(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 (print-interval z)
    (newline)
    (display "[")
    (display (lower-bound z))
    (display ", ")
    (display (upper-bound z))
    (display "]"))

; (i) Test Lem's complaint
; Take 2 resistors [3.5, 3.8] and [10, 10.3]
(define computation1 
    (par1 (make-interval 3.5 3.8) (make-interval 10 10.3)))
(define computation2 
    (par2 (make-interval 3.5 3.8) (make-interval 10 10.3)))
(print-interval computation1) ; [2.48, 2.9]
(print-interval computation2) ; [2.6, 2.77]
; => Lem's complaint is valid, we get two different results

; (ii) Let's define A and B using center-percent form
(define A (make-center-percent 50 5))
(define B (make-center-percent 100 8))

; Operation A/A
(define AA (div-interval A A))
(center AA) ;Value: 1.0050125313283207
(percent AA) ;Value: 9.97506234413964

; Operation A/B
(define AB (div-interval A B))
(center AB) ;Value: .5052334943639292
(percent AB) ;Value: 12.948207171314744

; => As we can observe, center of A/A is not exactly "1"
;   also, center of A/B is not exactly "0.5"
; Hence there's something flawed in our interval operations

; Let's try one more operation 1/A (which I found out helpful
; for next exercise)
(define one (make-center-percent 1 0))
(define 1A (div-interval one A))
(center 1A) ; 2.0050125313283207e-2 (~0.002)
(percent 1A) ; 4.999999999999995 (~5%)

; Also, A/1
(define A1 (div-interval A one))
(center A1) ;Value: 50.
(percent A1) ;Value: 5.