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


 
Class Rational {
      \\ this is a compact version for this task
      numerator as decimal, denominator as decimal
      gcd=lambda->0
      lcm=lambda->0
      operator "+" {
           Read l
           denom=.lcm(l.denominator, .denominator)
           .numerator<=denom/l.denominator*l.numerator+denom/.denominator*.numerator
           if .numerator==0 then denom=1
           .denominator<=denom
      }
      Group Real {
            value {
                  link parent numerator, denominator to n, d
                  =n/d
            }
      }
      Group ToString$ {
           value {
                  link parent numerator, denominator to n, d
                  =Str$(n)+"/"+Str$(d,"")
            }      
      }
      class:
      Module Rational (.numerator, .denominator) {
            if .denominator<=0 then Error "Positive only denominator"
            gcd1=lambda (a as decimal, b as decimal) -> {
                  if a<b then swap a,b
                  g=a mod b
                  while g {
                        a=b:b=g: g=a mod b
                  }
                        =abs(b)
            }
            .gcd<=gcd1
            .lcm<=lambda gcd=gcd1 (a as decimal, b as decimal) -> {
                  =a/gcd(a,b)*b
            }
      }
}
sum=rational(1, 1)
onediv=rational(1,1)
divcand=rational(1,1)
Profiler
For sum.denominator= 2 to 2**15 {
      divcand.denominator=sum.denominator
      For onediv.denominator=2 to sqrt(sum.denominator) {
            if sum.denominator mod onediv.denominator = 0 then {
                  divcand.numerator=onediv.denominator
                  sum=sum+onediv+divcand
            }
      }
      if sum.real=1 then Print sum.denominator;" is perfect"
      sum.numerator=1
}
Print timecount
 