Arithmetic/Rational: Difference between revisions

Lingo added
(Lingo added)
Line 1,833:
8128
</pre>
 
=={{header|Lingo}}==
A new 'frac' data type can be implemented like this:
<lang lingo>-- parent script "Frac"
property num
property denom
 
----------------------------------------
-- @constructor
-- @param {integer} numerator
-- @param {integer} [denominator=1]
----------------------------------------
on new (me, numerator, denominator)
if voidP(denominator) then denominator = 1
if denominator=0 then return VOID -- rule out division by zero
g = me._gcd(numerator, denominator)
if g<>0 then
numerator = numerator/g
denominator = denominator/g
else
numerator = 0
denominator = 1
end if
if denominator<0 then
numerator = -numerator
denominator = -denominator
end if
me.num = numerator
me.denom = denominator
return me
end
 
----------------------------------------
-- Returns string representation "<num>/<denom>"
-- @return {string}
----------------------------------------
on toString (me)
fp = the floatPrecision
the floatPrecision = 0
res = me.num&"/"&me.denom
the floatPrecision = fp
return res
end
 
----------------------------------------
--
----------------------------------------
on _gcd (me, a, b)
if a = 0 then return b
if b = 0 then return a
if a > b then return me._gcd(b, a mod b)
return me._gcd(a, b mod a)
end</lang>
 
Lingo does not support overwriting built-in operators, so 'frac'-operators must be implemented as functions:
<lang lingo>-- Frac library (movie script)
 
----------------------------------------
-- Utility function/shortcut for creating 'frac' values
-- @param {integer} numerator
-- @param {integer} denominator
-- @return {instance}
----------------------------------------
on frac (numerator, denominator)
return script("Frac").new(numerator, denominator)
end
 
----------------------------------------
-- All functions below this comment only support 'fracs', i.e. instances
-- of the Frac Class, as argument. An integer is casted to frac via frac(i).
----------------------------------------
 
-- Optionally supports more than 2 arguments
on fAdd (a, b) -- ...
res = a
repeat with i = 2 to the paramCount
p = param(i)
if integerP(p) then p = frac(p)
num = res.num * p.denom + res.denom * p.num
denom = res.denom * p.denom
res = frac(num, denom)
end repeat
return res
end
 
on fSub (a, b)
return frac(a.num * b.den - a.den * b.num, a.den * b.den)
end
 
-- Optionally supports more than 2 arguments
on fMul (a, b) -- ...
res = a
repeat with i = 2 to the paramCount
p = param(i)
if integerP(p) then p = frac(p)
res = frac(res.num * p.num, res.denom * p.denom)
end repeat
return res
end
 
on fDiv (a, b)
return frac(a.num * b.denom, a.denom * b.num)
end
 
on fAbs (f)
return frac(abs(f.num), f.denom)
end
 
on fNeg (f)
return frac(-f.num, f.denom)
end
 
on fEQ (a, b)
diff = fSub(a, b)
return diff.num=0
end
 
on fNE (a, b)
return not fEQ (a, b)
end
 
on fGT (a, b)
diff = fSub(a, b)
return diff.num>0
end
 
on fLT (a, b)
diff = fSub(a, b)
return diff.num<0
end
 
on fGE (a, b)
diff = fSub(a, b)
return diff.num>=0
end
 
on fLE (a, b)
diff = fSub(a, b)
return diff.num<=0
end</lang>
Usage:
<lang lingo>f = frac(2,3)
put f.toString()
-- "2/3"
 
-- fractions are normalized on the fly
f = frac(4,6)
put f.toString()
-- "2/3"
 
-- casting integer to frac
f = frac(23)
put f.toString()
-- "23/1"</lang>
 
Finding perfect numbers:
<lang lingo>-- in some movie script
----------------------------------------
-- Prints all perfect numbers up to n
-- @param {integer|float} n
----------------------------------------
on findPerfects (n)
repeat with i = 2 to n
sum = frac(1, i)
cnt = sqrt(i)
repeat with fac = 2 to cnt
if i mod fac = 0 then sum = fAdd(sum, frac(1, fac), frac(fac, i))
end repeat
if sum.denom = sum.num then put i
end repeat
end</lang>
<lang lingo>findPerfects(power(2, 19))
-- 6
-- 28
-- 496
-- 8128</lang>
 
=={{header|Lua}}==
Anonymous user