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.