#lang racket (define (add-interval x y) (make-interval (+ (lower-bound x) (lower-bound y)) (+ (upper-bound x) (upper-bound y)))) (define (mul-interval x y) (define p1 (* (lower-bound x) (lower-bound y))) (define p2 (* (lower-bound x) (upper-bound y))) (define p3 (* (upper-bound x) (lower-bound y))) (define 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))))) ;;;;;;;;; ;; 2.7 ;; ;;;;;;;;; (define (make-interval a b) (if (<= a b) (cons a b) (error "lower bound must not be greater than upper bound" a b))) (define (lower-bound i) (car i)) (define (upper-bound i) (cdr i)) ;;;;;;;;; ;; 2.8 ;; ;;;;;;;;; (define (sub-interval x y) (make-interval (- (lower-bound x) (upper-bound y)) (- (upper-bound x) (lower-bound y)))) ;;;;;;;;; ;; 2.9 ;; ;;;;;;;;; (define (width i) (/ (- (upper-bound i) (lower-bound i)) 2.0)) (define a (make-interval 0.2 0.4)) (define b (make-interval 1.1 1.5)) (width a) ;; 0.1 (width b) ;; 0.19999999999999996 (width (add-interval a b)) ;; 0.29999999999999993 (width (sub-interval a b)) ;; 0.3 (width (mul-interval a b)) ;; 0.19000000000000003 (width (div-interval a b)) ;; 0.11515151515151516 ;; In general, the width of the sum or difference of intervals is the sum of the ;; widths. However the widths of the product or quotient of intervals depends on ;; the upper and lower bounds of the intervals and not just on their widths. (define b2 (make-interval 0.1 0.5)) ; same width as b (width (mul-interval a b2)) ;; 0.09 (width (div-interval a b2)) ;; 1.8 ;;;;;;;;;; ;; 2.10 ;; ;;;;;;;;;; (define (contains-zero? i) (<= (* (upper-bound i) (lower-bound i)) 0)) (define (new-div-interval x y) (if (contains-zero? y) (error "divisor interval cannot contain zero" (lower-bound y) (upper-bound y)) (mul-interval x (make-interval (/ 1.0 (upper-bound y)) (/ 1.0 (lower-bound y)))))) ;;;;;;;;;; ;; 2.11 ;; ;;;;;;;;;; ;; The nine cases are: ;; x positive and y positive, ;; x positive and y negative, ;; x negative and y positive, ;; x negative and y negative, ;; x contains zero and y positive, ;; x contains zero and y negative, ;; y contains zero and x positive, ;; y contains zero and x negative, ;; x and y both contain zero; only this last case needs four multiplications. (define (new-mul-interval x y) (define xl (lower-bound x)) (define xu (upper-bound x)) (define yl (lower-bound y)) (define yu (upper-bound y)) (cond [(and (>= xl 0) (>= yl 0)) (make-interval (* xl yl) (* xu yu))] [(and (>= xl 0) (<= yu 0)) (make-interval (* xu yl) (* xl yu))] [(and (<= xu 0) (>= yl 0)) (make-interval (* xl yu) (* xu yl))] [(and (<= xu 0) (<= yu 0)) (make-interval (* xu yu) (* xl yl))] [(>= yl 0) (make-interval (* xl yu) (* xu yu))] [(<= yu 0) (make-interval (* xu yl) (* xl yl))] [(>= xl 0) (make-interval (* xu yl) (* xu yu))] [(<= xu 0) (make-interval (* xl yu) (* xl yl))] [else (define p1 (* xl yl)) (define p2 (* xl yu)) (define p3 (* xu yl)) (define p4 (* xu yu)) (make-interval (min p1 p2 p3 p4) (max p1 p2 p3 p4))])) (define x1 (make-interval 1 2)) (define x2 (make-interval -2 -1)) (define x3 (make-interval -1 2)) (define y1 (make-interval 3 5)) (define y2 (make-interval -5 -3)) (define y3 (make-interval -3 5)) (define (equal-interval? x y) (and (= (lower-bound x) (lower-bound y)) (= (upper-bound x) (upper-bound y)))) (define xs (list x1 x1 x1 x2 x2 x2 x3 x3 x3)) (define ys (list y1 y2 y3 y1 y2 y3 y1 y2 y3)) (for/and ([x xs] [y ys]) (equal-interval? (mul-interval x y) (new-mul-interval x y))) ;; #t ;;;;;;;;;; ;; 2.12 ;; ;;;;;;;;;; (define (make-center-width c w) (make-interval (- c w) (+ c w))) (define (center i) (/ (+ (lower-bound i) (upper-bound i)) 2.0)) (define (make-center-percent c p) (make-center-width c (* c p))) (define (percent i) (/ (width i) (center i))) ;;;;;;;;;; ;; 2.13 ;; ;;;;;;;;;; ;; x = interval with center c1 and percent p1 ;; y = interval with center c2 and percent p2 ;; x has lower-bound c1 - c1 * p1 and upper-bound c1 + c1 * p1 ;; y has lower-bound c2 - c2 * p2 and upper-bound c2 + c2 * p2 ;; assuming all numbers are positive, the product ;; has lower-bound c1 * (1 - p1) * c2 * (1 - p2) ~= c1 * c2 * (1 - p1 - p2) ;; and upper-bound c1 * (1 + p1) * c2 * (1 + p2) ~= c1 * c2 * (1 + p1 + p2) ;; where we drop the insignificant second-order terms involving p1 * p2 ;; so the product has center c1 * c2 and width c1 * c2 * (p1 + p2) ;; so the tolerance of the product is p1 + p2 ;;;;;;;;;; ;; 2.14 ;; ;;;;;;;;;; (define (par1 r1 r2) (div-interval (mul-interval r1 r2) (add-interval r1 r2))) (define (par2 r1 r2) (define one (make-interval 1 1)) (div-interval one (add-interval (div-interval one r1) (div-interval one r2)))) (define r1 (make-center-percent 4 0.1)) (define r2 (make-center-percent 10 0.2)) (define circ1 (par1 r1 r2)) (center circ1) ;; 3.1539108494533226 (percent circ1) ;; 0.4432000000000001 (define circ2 (par2 r1 r2)) (center circ2) ;; 2.8511354079058036 (percent circ2) ;; 0.12920353982300886 ;;;;;;;;;; ;; 2.15 ;; ;;;;;;;;;; ;; I think so. It stands to reason that more uncertain inputs should increase the ;; uncertainty of the output. ;;;;;;;;;; ;; 2.16 ;; ;;;;;;;;;; ;; Simplifying an algebraic expression before doing the interval arithmetic will ;; usually decrease the uncertainty in the final answer, like in 2.15. ;; One way around this issue would be to choose a normal form for each equivalence ;; class of algebraic expressions and always use that form to compute the answer. ;; I'm not sure if that's possible though.