# ArsDigita University, Structure and Interpretation of Computer Programs

# Lecture Notes for Lecture 5 -- 5 October 2000

Topics covered in today's lecture:

### Arithmetic with Rational Numbers

n1/d1 + n2/d2 = (n1*d2 + n2*d1) / (d1*d2)
n1/d1 - n2/d2 = (n1*d2 - n2*d1) / (d1*d2)

n1/d1 * n2/d2 = (n1*n2) / (d1*d2)

(n1/d1) / (n2/d2) = (n1*d2) / (d1*n2)

n1/d1 = n2/d2 iff n1*d2 = n2*d1

Assume that we have a constructor called `make-rat`, which
takes a numerator and a denominator and returns a rational number
representation. Also assume that we have two selectors,
`numer` and `denom`. Both selectors take a rational
number representation. `numer` returns the numerator of the
rational number and `denom` returns the denominator of the
rational number.

`(define (add-rat x y)
(make-rat (+ (* (numer x) (denom y))
(* (numer y) (denom x)))
(* (denom x) (denom y))))
(define (sub-rat x y)
(make-rat (- (* (numer x) (denom y))
(* (numer y) (denom x)))
(* (denom x) (denom y))))
(define (mul-rat x y)
(make-rat (* (numer x) (numer y))
(* (denom x) (denom y))))
(define (div-rat x y)
(make-rat (* (numer x) (denom y))
(* (denom x) (numer y))))
(define (equal-rat? x y)
(= (* (numer x) (denom y))
(* (numer y) (denom x))))
`

We could also write `sub-rat` by writing `negate-rat`
then using it and `add-rat` to define `sub-rat`:
(define (negate-rat x)
(make-rat (- (numer x))
(denom x)))
(define (sub-rat x y)
(add-rat x (negate-rat y)))

How can we write the constructors and selectors? Scheme has a
compound structure called a pair which is constructed with the
primitive procedure `cons`. `cons` takes two arguments
and returns a compound data object containing the two arguments as
parts.
(define a (cons 2 3)

We can draw box and pointer diagrams to represent cons cells. A cons
cell is drawn as two connected squares. For the example above, the
first square would have an arrow pointing to the number 2 and the
second box would have an arrow pointing to the number 3. See the book
or the videotaped lecture to see what they look like.
How do we get the elements from a pair? The first box of the cons
cell is called the car. We would write `(car a)`, which would
return the number 2. The second box of the cons cell is called the
cdr. We would write `(cdr a)`, which would return the number
3.

Cons pairs have the property of closure. Anything constructed by cons
can be used as an input element to cons. For example,

`(define b (cons 7 8))
(define c (cons b 9))
`

How can we extract 7 from these pairs? `(car b)` or `(car
(car c))`. We can also write `(car (car c))` as `(caar
c)`.
How can we get 8 from these pairs? `(cdr b)` or `(cdr (car
c))` (which can also be written as `(cdar c)`).

Finally, how can we get 9? `(cdr c)`

Now that we know about `cons`, `car` and `cdr`,
let's write `make-rat`, `numer` and `denom`.

`(define (make-rat n d)
(cons n d))
(define (numer x)
(car x))
(define (denom x)
(cdr x))
`

These could also be written as follows:
(define make-rat cons)
(define numer car)
(define denom cdr)

And how can we display a rational number?
(define (print-rat x)
(newline)
(display (numer x))
(display "/")
(display (denom x)))

We're not reducing the rational numbers to the lowest terms. How
could we do this? By changing `make-rat`:
(define (make-rat n d)
(let ((g (gcd n d)))
(cons (/ n g) (/ d g))))

We could also implement `make-rat` as a procedure:
(define (make-rat n d)
(lambda (proc) (proc n d)))
(define (numer x)
(x (lambda (a b) a)))
(define (denom x)
(y (lambda (a b) b)))

Last update: October 2000