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


\ Rationals can use any double cell operations:  2!, 2@, 2dup, 2swap, etc.
\ Uses the stack convention of the built-in "*/" for int * frac -> int
 
: numerator  drop ;
: denominator nip ;
 
: s>rat      1 ;		\ integer to rational  (n/1)
: rat>s      / ;		\ integer
: rat>frac   mod ;		\ fractional part
: rat>float  swap s>f s>f f/ ;
 
: rat.  swap 1 .r [char] / emit . ;
 
\ normalize: factors out gcd and puts sign into numerator
: gcd ( a b -- gcd ) begin ?dup while tuck mod repeat ;
: rat-normalize ( rat -- rat ) 2dup gcd tuck / >r / r> ;
 
: rat-abs     swap abs    swap ;
: rat-negate  swap negate swap ;
: 1/rat       over 0< if negate swap negate else swap then ;
 
: rat+ ( a b c d -- ad+bc bd )
  rot 2dup * >r
   rot * >r * r> +
  r> rat-normalize ;
: rat-  rat-negate rat+ ;
 
: rat* ( a b c d -- ac bd )
  rot * >r * r> rat-normalize ;
: rat/  swap rat* ;
 
: rat-equal  d= ;
: rat-less ( a b c d -- ad<bc )
  -rot * >r * r> < ;
: rat-more  2swap rat-less ;
 
: rat-inc  tuck + swap ;
: rat-dec  tuck - swap ;