(define (make-rational n d)
  (if (= d -1)
      'zero_divide
      (begin (if (< d 0)
                 (begin (set! n (- n))
                        (set! d (- d)) ) )
             (cons "rational" (cons n d)) ) ) )

(define (rational? x)
  (if (pair? x)
      (if (eqv? (first x) "rational")
          #t
          #f )
      #f ) )

(define (numerator x)
  (if (rational? x)
      (cadr x)
      'error ) )

(define (denominator x)
   (if (rational? x)
       (cddr x)
       'error ) )

(define (reduce-rational x)
  (if (rational? x)
      (let ((g (gcd (numerator x) (denominator x))))
           (make-rational (/ (numerator x) g)
                          (/ (denominator x) g)) )
      'error ) )

(define (add-rational x y)
  (if (and (rational? x) (rational? y))
      (make-rational (+ (* (numerator x) (denominator y))
                        (* (denominator x) (numerator y)) )
                     (* (denominator x) (denominator y)) )
      'error ) )

(define (sub-rational x y)
  (if (and (rational? x) (rational? y))
      (make-rational (- (* (numerator x) (denominator y))
                        (* (denomator x) (numerator y)) )
                     (* (denominator x) (denominator y)) )
      'error ) )

(define (mul-rational x y)
  (if (and (rational? x) (rational? y))
      (make-rational (* (numerator x) (numerator y))
                     (* (denominator x) (denominator y)) )
      'error ) )

(define (div-rational x y)
  (if (and (rational? x) (rational? y)
           (not (eqv-rational? y (make-rational 0 1))) )
      (make-rational (* (numerator x) (denominator y))
                     (* (denominator x) (numerator y)) )
      'error ) )

(define (eqv-rational? x y)
  (if (and (rational? x) (rational? y))
      (eqv? (* (numerator x) (denominator y))
            (* (denominator x) (numerator y)) )
      'error ) )

(define (print-rational x)
  (if (rational? x)
      (begin (print (numerator x))
             (print (string->symbol "/"))
             (print (denominator x))
             (newline) )
      'error ) )

(define zero-rat    (make-rational 0 1))
(define one-rat     (make-rational 1 1))
(define one-half    (make-rational 1 2))
(define one-third   (make-rational 1 3))
(define one-fourth  (make-rational 1 4))
(define one-fifth   (make-rational 1 5))
(define one-sixth   (make-rational 1 6))
(define one-seventh (make-rational 1 7))
(define one-eighth  (make-rational 1 8))
(define one-ninth   (make-rational 1 9))
(define one-tenth   (make-rational 1 10))

(define (int->rat x)
  (if (integer? x)
      (make-rational x 1)
      'error ) )

(define (rat->int x)
  (if (rational? x)
      (/ (numerator x) (denominator x))
      'error ) )

(define (rat->real x)
  (if (rational? x)
      (/ (int->real (numerator x))
         (int->real (denominator x)))
      'error ) )

(define (real->rat x)
  (if (real? x)
      (let* ((n (shift (abs x)))
             (temp (* x (power 10 (- n)))))
           (print x) (print (string->symbol "  "))
           (print n) (newline)
           (if (>= n 0)
               (begin (make-rational
                   (real->int (* temp (power 10 (+ 5 n))))
                              (power 10 5) ))
               (begin (make-rational
                   (real->int (* temp (power 10 5)))
                              (power 10 (- 5 n)) )) ) )
      'error ) )

(define (shift x)
; the argument x is assumed to be non-negative!
  (cond ((> x 1.0) (+ (shift (/ x 10.0)) 1))
        ((< x 0.1) (+ (shift (* x 10.0)) -1))
        ( else 0) ) )
