Exercise 2.8 of SICP

Exercise 2.8: Using reasoning analogous to Alyssa’s, describe how the difference of two intervals may be computed. Define a corresponding subtraction procedure, called sub-interval.

In the resistor example, the resistor is measured at 6.8 ohm with a tolerance of 10%. This means the actual value is $$6.8 \pm 0.68$$, which makes the interval [6.12 , 7.48]. The other resistor is $$4.7 \pm 0.235$$ with the interval of [4.465 , 4.935]. Naively subtracting the two intervals would give, [1.655 , 2.545]. Which doesn’t seem wrong but it is. It is wrong because we are biasing the tolerance in one direction for both measurements. We assume that the first value is $$6.8-0.68$$ and second $$4.7-0.235$$. There is no basis to assume that the following case isn’t just as valid: $$6.8-0.68$$ and $$4.7+0.235$$. It’s even clearer with the interval of $$3 \pm 1$$ [2 , 4] and $$2 \pm 1$$ [1 , 3]. Naively subtracting these terms yields an interval of 0 length, [1,1] or $$1 \pm 0$$ which is nonsense. In order to make sure no tolerance bias exists that makes calculations seem more accurate than is possible, the worst case measurement error must be assumed. The intervals will become as wide as possible to not give a false sense of accuracy.

(define (sub-interval x y)
(make-interval (- (lower-bound x) (upper-bound y))
(- (upper-bound x) (lower-bound y))))
(define (make-interval a b) (cons a b))

(define (lower-bound inter) (car inter))
(define (upper-bound inter) (cdr inter))

(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))))
(define (div-interval x y)
(mul-interval x
(make-interval (/ 1.0 (upper-bound y))
(/ 1.0 (lower-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 (print int)
(newline)
(display "[")
(display (lower-bound int))
(display ",")
(display (upper-bound int))
(display "]")
(newline))

> (print (sub-interval (make-interval 6.12 7.48) (make-interval 4.465 4.935)))
[1.1850000000000005,3.0150000000000006]