# sicp-ex-2.12

jz

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.

```

danlucraft

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)))))

```

qz

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))))
```

dxdm

Two points about calculating the percentage with

```  (/ (width i) (center i))
```
• Because of division by 0, the percentage is undefined if center happens to be 0. However, given a center of 0, make-center-percent produces a 0-width interval. If this is a valid result, the percent selector should also produce a valid result given a center and width of 0. (It's fine for other widths to be undefined, though.)
• The ratio of width and center can be found without calculating width and center:
```    width / center
= (2 * width) / (2 * center)
= (upper-bound - lower-bound) / (upper-bound + lower-bound)
```

vi

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)
0
(* 100 (abs (/ (- (upper-bound i) (center i)) (center i))))))
```