Hello! I have been trying to make a calculator but, the issue is it’s all in a string and strings don’t run operators and special characters. So, an example would be this:
"123*428"
And this won’t be calculated so how would a perform the calculations with any string including:
You can use string.split(Input, Operator). Here’s a small example:
--Define usuable mathematic operations, with the operator and the function the operator should use
local Operations = {
{
Name = "+",
Func = function(A, B)
return A + B
end,
},
{
Name = "-",
Func = function(A, B)
return A - B
end,
}
}
local Input = "5+5"
local function Calculate(InputString)
--Go through the defined operaations till you find one that's used in the input string
for _, Operation in pairs(Operations) do
--Check for numbers on the right and left of the operator symbol (aka, "+", "-", etc)
--string.split converts the string into a table by using the delimiter (in this case, the operation) to "split" the string into pieces.
local Numbers = string.split(Input, Operation.Name)
--#Numbers == 2: Verifies a match was found
--tonumber(Numbers[1 - 2]): Verifies the numbers found can be converted to actual numbers
if #Numbers == 2 and tonumber(Numbers[1]) and tonumber(Numbers[2]) then
--If everything passes, the operation is run
return Operation.Func(Numbers[1], Numbers[2])
end
end
--Couldn't calculate the number, maybe there was more than 1 operation?
return 0
end
print(Calculate(Input))
I encourage you to look through the code and ask any questions. The above example is REALLY simple. I’ve tried to document it as much as possible.
Edit: I’ve kinda overengineered this example, now that I think of it…
That’s odd, I’m getting 25. Make sure you’re only doing 1 operation, for example, 5+5, because this “calculator” can’t handle more than 1 operation, aka, 5+5-5 won’t work and it’ll just return 0.
Actually, that would be pretty simple. You can make it calculate the number every time a new operator is added, just make sure it doesn’t take the new operator.
When the player types in an operator, the input would be “5 + 5 *”, assuming they typed the * operator. What you need to do, is change it into “5 + 5” so it can be calculated to 10, and then add the the * operator back in, changing it into “10 *”.
But, then you have to take in the order of operations because “10 * 2” is different from “5 + 10”, and the whole mess that brings. I suggest you try experimenting around with string formatting and string patterns, if you really want to be able to do multiple operations at once.
I worked my head around this a bit and came up with this module:
local operators = { "+", "-", "*", "/", "%", "^" }
local function operate(r,o,n)
if o == "+" then r += n
elseif o == "-" then r -= n
elseif o == "*" then r *= n
elseif o == "/" then r /= n
elseif o == "%" then r %= n
elseif o == "^" then r ^= n
end
return r
end
local function getOperatorPos(str)
for i,c in ipairs(str:split("")) do
if table.find(operators, c) then return i,c end
end
end
local function opSplit(str)
str ..= "+"
local strTbl = {}
local opCount = 0
for i,c in ipairs(str:split("")) do
if table.find(operators, c) then
opCount += 1
if opCount > 1 then
table.insert(strTbl, str:sub(1, i - 1))
str = str:sub(i, #str - 1)
end
end
end
if not strTbl[1] then strTbl[1] = str end
return strTbl
end
local function calculate(str, res)
local opPos, op = getOperatorPos(str)
if not opPos then return end
local num1 = opPos == 1 and res or tonumber(str:sub(1, opPos - 1))
local num2 = tonumber(str:sub(opPos + 1, #str))
if not num1 or not num2 then return end
return operate(num1, op, num2)
end
return function(str)
assert(typeof(str) == "string", "Invalid format, string expected")
str = string.gsub(str, " ", "")
local result
local strTbl = opSplit(str)
for _,s in ipairs(strTbl) do
local opRes = calculate(s, result)
if not opRes then break end
result = opRes
end
return result
end
However I’m quite disappointed for not being able to figure out how to make it follow PEMDAS lol
Example code:
local calculator = require(game:GetService("ReplicatedStorage").Calculator)
print(calculator("10/2+3"))