Task

Create a reasonably complete implementation of rational arithmetic in the particular language using the idioms of the language.



Example

Define a new type called frac with binary operator "//" of two integers that returns a structure made up of the numerator and the denominator (as per a rational number).

Further define the appropriate rational unary operators abs and '-', with the binary operators for addition '+', subtraction '-', multiplication '×', division '/', integer division '÷', modulo division, the comparison operators (e.g. '<', '≤', '>', & '≥') and equality operators (e.g. '=' & '≠').

Define standard coercion operators for casting int to frac etc.

If space allows, define standard increment and decrement operators (e.g. '+:=' & '-:=' etc.).

Finally test the operators:
Use the new type frac to find all perfect numbers less than 219 by summing the reciprocal of the factors.



Related task

   Perfect Numbers


 
(define x 3/7)
(define y 9/11)
(define z -2/5)
 
; demonstrate builtin functions:
 
(print "(abs " z ") = " (abs z))
(print "- " z " = " (- z))
(print x " + " y " = " (+ x y))
(print x " - " y " = " (- x y))
(print x " * " y " = " (* x y))
(print x " / " y " = " (/ x y))
(print x " < " y " = " (< x y))
(print x " > " y " = " (> x y))
 
; introduce new functions:
 
(define (+:= x) (+ x 1))
(define (-:= x) (- x 1))
 
(print "+:= " z " = " (+:= z))
(print "-:= " z " = " (-:= z))
 
; finally, find all perfect numbers less than 2^15:
 
(lfor-each (lambda (candidate)
      (let ((sum (lfold (lambda (sum factor)
                     (if (= 0 (modulo candidate factor))
                        (+ sum (/ 1 factor) (/ factor candidate))
                        sum))
                  (/ 1 candidate)
                  (liota 2 1 (+ (isqrt candidate) 1)))))
         (if (= 1 (denominator sum))
            (print candidate (if (eq? sum 1) ", perfect" "")))))
   (liota 2 1 (expt 2 15)))
 