# My Fraction Class

Hi guys! I have been working on a fraction class for a while. The usage is documented inside the project.

``````
-- My fraction class

function setup()
-- Usage of the fraction class
half = fraction(1, 2) -- Traditional syntax, works well with all fractions, including decimals
third = fraction(1, 3)
quarter = fraction(1 / 4) -- Alternative syntax, does not work for fractions such as 1/3
fifth = fraction(.2) -- note how the denominator defaults to 1
pi = fraction(355,113)
print("Half =", half)
print("Third =", third, "which in decimal is =", third.value)
print("Two Quarters =", quarter * 2)
print("Half a fifth =", half * fifth)
print("Fifth =", fifth)
print("A Third plus a half =", third + half )
print("A half minus a third =", half - third)
print("One and a half =", half + 1)
print("Half minus one =", half - 1)
print("Half didvided by a third =", half/third)
print("Half to the power of 3 =", half ^ 3)
print("Half to the power of minus 3 =", half ^ -3)
print("Negative half =", -half)
print("My fraction approximation of Pi =", pi.value, "and Codea/Luas approximation =", math.pi)
print("Enjoy!")
end

fraction = class()

function math.hcf(n, d)
while not (d == 0) do
n, d = d, n % d
end
return n
end

function fraction:init(n, d)
self.n = n
self.d = d or 1
self:_set()
self.value = self.n / self.d
end

function fraction:_set()
if not (self.n % 1 == 0) then
local zeros = 0
local rem = .5
while not (rem % 1 == 0) do
zeros = zeros + 1
rem = self.n * (10 ^ zeros)
end
self.n = rem
self.d = self.d * (10 ^ zeros)
end
if not (self.d % 1 == 0) then
local zeros = 0
local rem = 0.5
while not (rem % 1 == 0) do
zeros = zeros + 1
rem = self.d * (10 ^ zeros)
end
self.n = self.n * (10 ^ zeros)
self.d = rem
end
local gcd = math.hcf(self.n, self.d)
self.n = self.n / gcd
self.d = self.d / gcd
end

if type(t) == "number" then
return fraction(self.n + self.d * t, self.d)
elseif type(t) == "table" and t.n and t.d then
return fraction(self.n * t.d + t.n * self.d, self.d * t.d)
end
end

function fraction:__sub(t)
if type(t) == "number" then
return fraction(self.n - self.d * t, self.d)
elseif type(t) == "table" and t.n and t.d then
return fraction(self.n * t.d - t.n * self.d, self.d * t.d)
end
end

function fraction:__mul(t)
if type(t) == "number" then
return fraction(self.n * t, self.d)
elseif type(t) == "table" and t.n and t.d then
return fraction(self.n * t.n, self.d * t.d)
end
end

function fraction:__div(t)
if type(t) == "number" then
return fraction(self.n, self.d * t)
elseif type(t) == "table" and t.n and t.d then
return fraction(self.n * t.d, self.d * t.n)
end
end

function fraction:__unm()
return fraction(-self.n, self.d)
end

function fraction:__pow(exp)
local n = fraction(1)
if exp > 0 then
for i = 1, exp do
n = n * fraction(self.n, self.d)
end
elseif exp < 0 then
for i = -1, exp, -1 do
n = n / fraction(self.n, self.d)
end
end
return n
end

function fraction:__tostring()
return self.n.."/"..self.d
end
``````

Thanks!

Might want to verify that pow() is passed an integer.

Thanks @SciQuest, I am working on an improved version of this, because all the operators only work with the fraction to the left, I will post my code in a day or two.

Here is my new and improved code! It supports Boolean testing, Concatenation, and all operators excluding ^ and %.

``````-- Fraction class by Jordan Arenstein

fraction = class()

--[[
FEATURES =
Automatically simplifies
Automatically converts floats to integers without changing the value of the fraction
Supports the +, -, *, /, and .. operators
Supports print()
Supports boolean testing using ==, <, >, <=, >= operators

CUTBACKS =
Doesn't support ^ and % operators... yet
Boolean testing only works when comparing fractions

]]--

function setup()
half = fraction(1, 2)
print("One half = "..half)
print("Is one half(fraction(1, 2)) equal to fraction(1/2)? " .. ((half == fraction(1 / 2)) and "true" or "false"))
third = fraction(1, 3)
print("A third plus a half = ".. (third + half))
print("A third minus a half = ".. (third - half))
print("A third times a half = ".. (third * half))
print("A third divided by a half = ".. (third / half))
quarter = half * half
print("A third("..third..") in decimal = ".. third:decimal())
print("A quarter is less than a half = ".. ((quarter < half) and "true" or "false"))
print("1 and a half = ".. (1 + half))
print("1 minus a third = ".. (1 - third))
print("5 halves = ".. (5 * half))
print("2 / half = ".. (2 / half))
print("Half / 2 = ".. (half / 2))
print("Codea's representation of Pi = ".. math.pi)
Pi = fraction(355, 113)
print("My representation of Pi = ".. Pi:decimal())
end

function math.hcf(n, d) -- Function to find the highest common factor between 2 numbers
while d ~= 0 do
n, d = d, n % d
end
return n
end

function fraction:init(n, d)
d = d or 1 -- Default the denominator to 1 so the syntax 1/2 works
if n % 1 ~= 0 then -- If the numerator isn't whole then...
local z = 0 -- The number of zeros needed to times the numerator by until it is a whole number
local r = 0.1 -- The remainder
while r % 1 ~= 0 do
z = z + 1
r = n * (10 ^ z) -- 10 to the power of z
end
n = r -- Make n a whole number
d = d * (10 ^ z) -- Multiply the denominator too, so the ratio stays the same
end
-- Same proccess for the denominator
if d % 1 ~= 0 then
local z = 0
local r = 0.1
while r % 1 ~= 0 do
z = z + 1
r = d * (10 ^ z)
end
n = n * (10 ^ z)
d = r
end
local gcd = math.hcf(n, d)
self.n = n / gcd
self.d = d / gcd
end

function fraction:decimal()
return self.n / self.d
end

if type(n) == "number" then -- If the value to the right of the operator is a number (fract + 2)
return fraction(self.n + self.d * n, self.d)
end
if type(self) == "number" then -- If the value to the left is a number (2 + fract)
return fraction(n.n + n.d * self, n.d)
end
-- Then both must be fractions!
return fraction(self.n * n.d + n.n * self.d, self.d * n.d)
end

function fraction:__sub(n)
if type(n) == "number" then -- If the value to the right of the operator is a number (fract - 2)
return fraction(self.n - self.d * n, self.d)
end
if type(self) == "number" then -- If the value to the left is a number (2 - fract)
return fraction(n.d * self - n.n, n.d)
end
-- Then both must be fractions!
return fraction(self.n * n.d - n.n * self.d, self.d * n.d)
end

function fraction:__mul(n)
if type(n) == "number" then -- If the value to the right of the operator is a number (fract * 2)
return fraction(self.n * n, self.d)
end
if type(self) == "number" then -- If the value to the left is a number (2 * fract)
return fraction(n.n * self, n.d)
end
-- Then both must be fractions!
return fraction(self.n * n.n, self.d * n.d)
end

function fraction:__div(n)
if type(n) == "number" then -- If the value to the right of the operator is a number (fract / 2)
return fraction(self.n, self.d * n)
end
if type(self) == "number" then -- If the value to the left is a number (2 / fract)
return fraction(n.n * self, n.d)
end
-- Then both must be fractions!
return fraction(self.n * n.d, self.d * n.n)
end

function fraction:__unm()
return fraction(-self.n, self.d)
end

--[[ Removing this one, as it is extremely buggy. See:
function fraction:__mod(n)
-- The formula for modulo = a % b == a - math.floor(a/b)*b
if type(n) == "number" then
return self - math.floor((self / n):decimal()) * n
end
if type(self) == "number" then
return self - math.floor((self / n):decimal()) * n
end
return fraction(self.n * n.d, self.d * n.n)
end
]]--

function fraction:__concat(str)
if type(self) == "table" and self.n and self.d then -- It has been called in the format fract .. str
return self:__tostring() .. str
elseif type(str) == "table" and str.n and str.d then -- It has been called in the format str .. fract
return self .. str:__tostring()
end
end

function fraction:__tostring()
return self.n .. "/" .. self.d
end

function fraction:__eq(n)
if self.d == n.d and self.n == n.n then
return true
end
return false
end

function fraction:__lt(n) -- The < operator
return self.n * n.d < n.n * self.d
end

function fraction:__le(n) -- The <= operator
return self.n * n.d <= n.n * self.d
end

function fraction:__gt(n) -- The < operator
return self.n * n.d > n.n * self.d
end

function fraction:__ge(n) -- The <= operator
return self.n * n.d >= n.n * self.d
end
``````