[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Algorithm for RATIONALIZE



; This code assumes -perfect- arithmetic, so it wont get the
; exactness correct in any particular implementation.
; To really understand how this works, you should go learn about continued
; fractions. 

(define (rationalize x e)
  (simplest-rational (- x e) (+ x e)))

; Produces the simplest rational between X and Y inclusive.
; (In the comments that follow, [x] means floor(x).)
(define (simplest-rational x y)
  (define (simplest-rational-internal x y)	; assumes 0 < X < Y
    (let ((fx (floor x))	; [X] <= X < [X]+1
	  (fy (floor y)))	; [Y] <= Y < [Y]+1, also [X] <= [Y]
      (cond ((not (< fx x))
	     ;; X is an integer so X is the answer:
	     fx)
	    ((= fx fy)
	     ;; [Y] = [X] < X < Y so expand the next term in the continued
	     ;; fraction:
	     (+ fx (/ (simplest-rational-internal (/ (- y fy)) (/ (- x fx))))))
	    (else
	     ;; [X] < X < [X]+1 <= [Y] <= Y so [X]+1 is the answer:
	     (+ 1 fx)))))
  (cond ((< y x)
	 ;; Y < X so swap and try again:
	 (simplest-rational y x))
	((not (< x y))
	 ;; X = Y so if that is a rational that is the answer, otherwise
	 ;; there is nothing we can return at all.
	 (if (rational? x) x (error)))
	((positive? x) 
	 ;; 0 < X < Y which is what SIMPLEST-RATIONAL-INTERNAL expects:
	 (simplest-rational-internal x y))
	((negative? y)
	 ;; X < Y < 0 so 0 < -Y < -X and we negate the answer:
	 (- (simplest-rational-internal (- y) (- x))))
	(else
	 ;; X <= 0 <= Y so zero is the answer:
	 0)))