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


There are a few ways to do this problem, e.g.:

  1. totally redefine the internal structure of an interval, such that you cons the center and the percent
  2. just define the constructor in terms of the width and percent, and add center and percent selectors
 ;; ex 2.12 
 (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 (center i) (/ (+ (upper-bound i) (lower-bound i)) 2)) 
 ;; Percent is between 0 and 100.0 
 (define (make-interval-center-percent c pct) 
   (let ((width (* c (/ pct 100.0)))) 
     (make-interval (- c width) (+ c width)))) 
 (define (percent-tolerance i) 
   (let ((center (/ (+ (upper-bound i) (lower-bound i)) 2.0)) 
         (width (/ (- (upper-bound i) (lower-bound i)) 2.0))) 
     (* (/ width center) 100))) 
 ;; A quick check: 
 (define i (make-interval-center-percent 10 50)) 
 (lower-bound i) 
 (upper-bound i) 
 (center i) 
 (percent-tolerance i) 
 ; The above returns 
 ;Value: i 
 ;Value: 5. 
 ;Value: 15. 
 ;Value: 10. 
 ;Value: 50. 


Do you think we need to abs the width as well? (this uses proportion instead of percent)

 ; e.g. for (make-center-percent -10 0.05) 
 (define (make-center-percent c p) 
   (make-interval (- c (abs (* c p))) (+ c (abs (* c p))))) 


I think make-center-width, center, width can be used here to make it concise.

 (define (make-center-percent c p) 
   (make-center-width c (* c p))) 
 (define (percent i) 
   (/ (width i) (center i))) 

 ;We are talking about percentages rather than fractions.  Therefore  
 (define (make-center-percent c p)  
    (make-interval (- c (abs (* c (/ p 100))))  
                   (+ c (abs (* c (/ p 100)))))) 
 ;Also, for the percentage selector 
   (define (percent i)  
         (* 100 (/ (width i) (center i)))) 


Two points about calculating the percentage with

  (/ (width i) (center i))
    width / center 
  = (2 * width) / (2 * center) 
  = (upper-bound - lower-bound) / (upper-bound + lower-bound)


As dxdm mentions, if we have a center of zero, percentage in terms of a center which is zero is not well defined. Logically it is always zero, so I've defined a solution which lets the percentage be zero where the center is zero. Also, I don't use `width` as a procedure since they mentioned we'd only get to keep `center` as it appears in the previous definition:

 (define (make-center-percent c p) 
   (let ((width (abs (* (/ p 100) c)))) 
   (make-interval (- c width) (+ c width)))) 
 (define (percent i) 
   (if (= (center i) 0) 
     (* 100 (abs (/ (- (upper-bound i) (center i)) (center i))))))