I’m trying to make a calculator, and this is how it works:
The player clicks any buttons on the calculator gui and it adds whatever they clicked to a table that is in a module.
When they click ‘=’ it calculates whatever they put in, and shows the result.
What I need help with is, in the table there’s everything they put in, and I need to somehow calculate that.
If you don’t know what I mean, this is the script:
local equals = script.Parent
local frame = equals.Parent
local main = frame.Parent
local result = main.Result
local inputModule = game.ReplicatedStorage.Input
local inputTable = require(inputModule)
equals.MouseButton1Click:Connect(function()
local calculation = ""
for _,input in pairs(inputTable) do
calculation ..= input
end
if calculation ~= nil then
result.Text = calculation
else
result.Text = "Error"
end
end)
^ ‘calculation’ is a string, instead I basically want it to literally DO it. (Calculate it)
Example, you put 3+6*7, the table would literally be {3,+,6,*,7}, then the loop makes a string: 3+6*7 (‘calculation’ variable), which I want to solve instead of making a string, and make (‘result’)'s text, that.
So after you are able to turn strings into that, you will have to compute everything “inside” a parenthesis.
After all operations inside parentheses are computed, compute all the exponentiation, division, and multiplication, and finally, run it from the first index to the last, adding and subtracting all those numbers.
Adding functions (e.g. sine) is just as simple as they can be treated like a special token.
The easiest option is probably to use dthecoolest’s answer for parsing. It seems that all you have to do is load a string expression and do something with the output.
Another option would be to write a parser yourself. This is not the most practical thing to do, but it can be quite educational. Normally, you would be able to use Lua’s ‘load’ global, but I believe that it is not available in ROBLOX. Also, things can get quite complicated, cause you cannot just iterate through an equation from start to finish. For example, the equation ‘3 * 4 ^ 2’ cannot be solved like this:
Here’s a calculate function I wrote based on that video. I’m only supporting * and +, and also not doing any checking to see if what is entered is valid, so if you actually used this you might want to add that or wrap it in a pcall.
function tokenize(expression)
-- turn an expression to a table of tokens
-- for example "42+3141*271" -> {42, "+", 3141, "*", 271}
local result = {}
local part = ""
for i = 1, #expression do
local character = expression:sub(i,i)
if character == "+" or character == "*" then
if part ~= "" then
table.insert(result, tonumber(part))
part = ""
end
table.insert(result, character)
else
part = part .. character
end
end
if part ~= "" then
table.insert(result, tonumber(part))
end
return result
end
function to_postfix(tokens)
-- shunting yard algorithm learned from
-- https://www.youtube.com/watch?v=Wz85Hiwi5MY
stack = {}
queue = {}
for _, token in pairs(tokens) do
if token == "*" then
-- Push on top of stack
table.insert(stack, 1, "*")
elseif token == "+" then
-- First move any multiplications from stack to the queue
while #stack > 0 and stack[1] == "*" do
table.remove(stack, 1)
table.insert(queue, "*")
end
-- Push + on top of stack
table.insert(stack, 1, "+")
else
-- Numbers go in the queue
table.insert(queue, token)
end
end
-- Finally move anything left in the stack onto the queue
while #stack > 0 do
table.insert(queue, table.remove(stack, 1))
end
return queue
end
function calculate_postfix(postfix)
local stack = {}
for _, token in pairs(postfix) do
local isNumber = token ~= "+" and token ~= "*"
if isNumber then
-- Push operand on stack
table.insert(stack, 1, token)
else
-- Pop operands from stack, compute result and push it on stack
if #stack < 2 then
print("Tried to compute", token, "but operands were missing")
return
end
local a = table.remove(stack, 1)
local b = table.remove(stack, 1)
if token == "+" then
table.insert(stack, 1, a + b)
end
if token == "*" then
table.insert(stack, 1, a * b)
end
end
end
return table.remove(stack, 1)
end
function calculate(expression)
-- Convert to tokens, then to postfix and calculate
local tokens = tokenize(expression)
local postfix = to_postfix(tokens)
local result = calculate_postfix(postfix)
return result
end
print(calculate("42+3141*271"))
You can use loadstring to do it. First, you have to tick LoadstringEnabled in ServerScriptService. Then, you can use loadstring(calculation). I haven’t tested this so please tell me if it doesn’t work.