Arithmetic/Rational: Difference between revisions
Content added Content deleted
(Lingo added) |
|||
Line 1,833: | Line 1,833: | ||
8128 |
8128 |
||
</pre> |
</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}}== |
=={{header|Lua}}== |