User:NXTBoy/Scripts/Fraction: Difference between revisions
From Legacy Roblox Wiki
< User:NXTBoy | Scripts
>NXTBoy No edit summary |
>NXTBoy No edit summary |
||
Line 1: | Line 1: | ||
{{lua|= | |||
local Fraction = {} | local Fraction = {} | ||
Fraction.new = function(num, denom) | Fraction.new = function(num, denom) | ||
Line 163: | Line 163: | ||
return f1 | return f1 | ||
end | end | ||
}} | |||
Using it: | Using it: |
Latest revision as of 17:53, 17 April 2012
local Fraction = {}
Fraction.new = function(num, denom)
return setmetatable({
numerator = num or 0,
denominator = denom or 0
}, Fraction):simplify()
end
Fraction.toFloat = function(self)
return self.numerator / self.denominator
end
Fraction.simplify = function(self)
for i = 2, self.q do
while self.p % i == 0 and self.q % i == 0 do
self.p = self.p / i
self.q = self.q / i
end
end
return self
end
-- Metatable bits and pieces
Fraction.__index = function(self, k)
if k == "p" or k == "top" then
return self.numerator
elseif k == "q" or k == "bottom" then
return self.denominator
else
return Fraction[k]
end
end
Fraction.__tostring = function(self)
return self.p.."/"..self.q
end
Fraction.__unm = function(self)
return Fraction.new(
-self.p,
self.q
)
end
Fraction.__pow = function(a, b)
if getmetatable(a) == Fraction and getmetatable(b) == Fraction then
return a:toFloat() ^ b:toFloat()
elseif getmetatable(a) == Fraction and type(b) == "number" then
return Fraction.new(
a.p ^ b,
a.q ^ b
)
elseif type(a) == "number" and getmetatable(b) == Fraction then
return a ^ b:toFloat()
else
error(string.format("attempt to raise a %s to the power of a %s", type(a), type(b)), 2)
end
end
Fraction.__add = function(a, b)
if getmetatable(a) == Fraction and getmetatable(b) == Fraction then
return Fraction.new(
a.p * b.q + a.q * b.p,
a.q * b.q
)
elseif getmetatable(a) == Fraction and type(b) == "number" then
return Fraction.new(
a.p + b * a.q,
a.q
)
elseif type(a) == "number" and getmetatable(b) == Fraction then
return Fraction.new(
b.p + a * b.q,
b.q
)
else
error(string.format("attempt to add a %s to a %s", type(a), type(b)), 2)
end
end
Fraction.__sub = function(a, b)
if getmetatable(a) == Fraction and getmetatable(b) == Fraction then
return Fraction.new(
a.p * b.q - a.q * b.p,
a.q * b.q
)
elseif getmetatable(a) == Fraction and type(b) == "number" then
return Fraction.new(
a.p - b * a.q,
a.q
)
elseif type(a) == "number" and getmetatable(b) == Fraction then
return Fraction.new(
b.p - a * b.q,
b.q
)
else
error(string.format("attempt to subtract a %s from a %s", type(a), type(b)), 2)
end
end
Fraction.__mul = function(a, b)
if getmetatable(a) == Fraction and getmetatable(b) == Fraction then
return Fraction.new(
a.p * b.p,
a.q * b.q
)
elseif getmetatable(a) == Fraction and type(b) == "number" then
return Fraction.new(
a.p * b,
a.q
)
elseif type(a) == "number" and getmetatable(b) == Fraction then
return Fraction.new(
a * b.p,
b.q
)
else
error(string.format("attempt to multiply a %s by a %s", type(a), type(b)), 2)
end
end
Fraction.__div = function(a, b)
if getmetatable(a) == Fraction and getmetatable(b) == Fraction then
return Fraction.new(
a.p * b.q,
a.q * b.p
)
elseif getmetatable(a) == Fraction and type(b) == "number" then
return Fraction.new(
a.p,
a.q * b
)
elseif type(a) == "number" and getmetatable(b) == Fraction then
return Fraction.new(
a * b.q,
b.p
)
else
error(string.format("attempt to divide a %s by a %s", type(a), type(b)), 2)
end
end
--Important bit
Fraction.fromFloat = function(input, maxDenominator)
maxDenominator = maxDenominator or 1e99
local f0 = Fraction.new(1, 0)
local f1 = Fraction.new(math.floor(input), 1)
local f2
local r = input % 1
local next_cf
while math.abs(r) >= 0.0001 do
r = 1 / r
next_cf = math.floor(r)
f2 = Fraction.new(
next_cf * f1.p + f0.p,
next_cf * f1.q + f0.q
)
-- Limit the denominator
if f2.denominator > maxDenominator then break end
-- remember the last two fractions
f0 = f1
f1 = f2
r = r - next_cf
end
return f1
end
Using it:
print(Fraction.fromFloat(1/3) + Fraction.fromFloat(1/2)) --5/6 print(Fraction.new(1, 6) + Fraction.new(1, 3)) --1/2 print(Fraction.fromFloat(math.pi, 100)) --22/7