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


with javascript_semantics
without warning  -- (several unused routines in this code)
 
constant NUM = 1, DEN = 2
 
type frac(object r)
    return sequence(r) and length(r)=2 and integer(r[NUM]) and integer(r[DEN])
end type
 
function normalise(object n, atom d=0)
    if sequence(n) then
        {n,d} = n
    end if
    if d<0 then
        n = -n
        d = -d
    end if
    atom g = gcd(n,d)
    return {n/g,d/g}
end function
 
function frac_new(integer n, d=1)
    return normalise(n,d)
end function
 
function frac_abs(frac r)
    return {abs(r[NUM]),r[DEN]}
end function
 
function frac_inv(frac r)
    return reverse(r)
end function
 
function frac_add(frac a, b)
    integer {an,ad} = a,
            {bn,bd} = b
    return normalise(an*bd+bn*ad, ad*bd)
end function
 
function frac_sub(frac a, b)
    integer {an,ad} = a,
            {bn,bd} = b
    return normalise(an*bd-bn*ad, ad*bd)
end function
 
function frac_mul(frac a, b)
integer {an,ad} = a,
        {bn,bd} = b
    return normalise(an*bn, ad*bd)
end function
 
function frac_div(frac a, b)
integer {an,ad} = a,
        {bn,bd} = b
    return normalise(an*bd, ad*bn)
end function
 
function frac_eq(frac a, b)
    return a==b
end function
 
function frac_ne(frac a, b)
    return a!=b
end function
 
function frac_lt(frac a, b)
    return frac_sub(a,b)[NUM]<0
end function
 
function frac_gt(frac a, b)
    return frac_sub(a,b)[NUM]>0
end function
 
function frac_le(frac a, b)
    return frac_sub(a,b)[NUM]<=0
end function
 
function frac_ge(frac a, b)
    return frac_sub(a,b)[NUM]>=0
end function
 
function is_perfect(integer num)
    frac total = frac_new(0)
    sequence f = factors(num,1)
    for i=1 to length(f) do
        total = frac_add(total,frac_new(1,f[i]))
    end for
    return frac_eq(total,frac_new(2))
end function
 
procedure get_perfect_numbers()
    atom t0 = time()
    integer lim = power(2,iff(platform()=JS?13:19))
    for i=2 to lim do
        if is_perfect(i) then
            printf(1,"perfect: %d\n",i)
        end if
    end for
    printf(1,"elapsed: %3.2f seconds\n",time()-t0)
 
    integer pn5 = power(2,12)*(power(2,13)-1) -- 5th perfect number
    if is_perfect(pn5) then
        printf(1,"perfect: %d\n",pn5)
    end if
end procedure
 
get_perfect_numbers()
