sicp-ex-2.10



<< Previous exercise (2.9) | Index | Next exercise (2.11) >>


jz

Basically, we're just using the error keyword.

  
 ;; ex 2.7 
 (define (make-interval a b) (cons a b)) 
 (define (upper-bound interval) (max (car interval) (cdr interval))) 
 (define (lower-bound interval) (min (car interval) (cdr interval))) 
  
 (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. (upper-bound y)) 
                                (/ 1. (lower-bound y))))) 
  
 (define (print-interval name i) 
   (newline) 
   (display name) 
   (display ": [") 
   (display (lower-bound i)) 
   (display ",") 
   (display (upper-bound i)) 
   (display "]")) 
  
 ;; Usage 
 (define i (make-interval 2 7)) 
 (define j (make-interval 8 3)) 
  
 (print-interval "i" i) 
 (print-interval "j" j) 
 (print-interval "i*j" (mul-interval i j)) 
 (print-interval "j*i" (mul-interval j i)) 
 (print-interval "i/j" (div-interval i j)) 
 (print-interval "j/i" (div-interval j i)) 
  
 ;; Gives: 
 ;; i: [2,7] 
 ;; j: [3,8] 
 ;; i*j: [6,56] 
 ;; j*i: [6,56] 
 ;; i/j: [.25,2.333333333333333] 
 ;; j/i: [.42857142857142855,4.] 
  
  
 ;; New definition: Division by interval spanning 0 should fail. 
 ;; Note that the operator <= has a different definition when using #lang racket and #lang sicp. When using #lang sicp the operators to <= should be reversed. 
 (define (div-interval x y) 
   (if (<= 0 (* (lower-bound y) (upper-bound y))) 
       (error "Division error (interval spans 0)" y) 
       (mul-interval x  
                     (make-interval (/ 1. (upper-bound y)) 
                                    (/ 1. (lower-bound y)))))) 
  
 (define span-0 (make-interval -1 1)) 
 (print-interval "i/j" (div-interval i j)) 
 (print-interval "i/span-0" (div-interval i span-0)) 
  
 ;; Results: 
 ;; i/j: [.25,2.333333333333333] 
 ;; ;Division error (interval spans 0) (-1 . 1) 
  

vi

Couldn't we simply check if upper and lower bound are equal? Also, what happens here when dividing by an interval that starts at a negative and ends at a positive?

 (div-interval (make-interval 0 1) (make-interval -2 2)) 

I propose this solution:

 (define (div-interval x y) 
   (if (= (upper-bound y) (lower-bound y)) 
     (error "division by zero interval") 
     (mul-interval x  
       (make-interval (/ 1.0 (upper-bound y)) 
                       (/ 1.0 (lower-bound y)))))) 

The answer above(vi) misunderstand the question, if the interval is zero(upper-bound = lower-bound), that's alright, it won't cause any problem, the problem is the interval spans zero (upper-bound > 0, and lower-bound < 0), then if the dividend happens to be zero, it will cause problem. The first answer(jz) is correct.