I've attempted it about three times and gotten a basic one cranked out by basically storing the input in an array as a string, parsing the numbers, then switching on the operator, in order to evaluate the integers, but I'm having a really hard time figuring out the chaining logic.
What should I do? What could be pseudocode? I really don't want to use 'eval'.
I've attempted it about three times and gotten a basic one cranked out by basically storing the input in an array as a string, parsing the numbers, then switching on the operator, in order to evaluate the integers, but I'm having a really hard time figuring out the chaining logic.
What should I do? What could be pseudocode? I really don't want to use 'eval'.
Share Improve this question edited Apr 4, 2023 at 11:00 Peter Mortensen 31.6k22 gold badges110 silver badges133 bronze badges asked Aug 30, 2015 at 1:04 spbspb 4,2396 gold badges24 silver badges30 bronze badges 4 |1 Answer
Reset to default 15For a simple calculator with only 5 operators (^, *, /, +, -) and no parentheses, you can do something like this. First, it is convenient to turn the string into an array of numbers and operators. Then, we go through the array looking for each operator in order of precedence, and applying the operator to the numbers preceding and following the it.
function tokenize(s) {
// --- Parse a calculation string into an array of numbers and operators
const r = [];
let token = '';
for (const character of s) {
if ('^*/+-'.includes(character)) {
if (token === '' && character === '-') {
token = '-';
} else {
r.push(parseFloat(token), character);
token = '';
}
} else {
token += character;
}
}
if (token !== '') {
r.push(parseFloat(token));
}
return r;
}
function calculate(tokens) {
// --- Perform a calculation expressed as an array of operators and numbers
const operatorPrecedence = [{'^': (a, b) => Math.pow(a, b)},
{'*': (a, b) => a * b, '/': (a, b) => a / b},
{'+': (a, b) => a + b, '-': (a, b) => a - b}];
let operator;
for (const operators of operatorPrecedence) {
const newTokens = [];
for (const token of tokens) {
if (token in operators) {
operator = operators[token];
} else if (operator) {
newTokens[newTokens.length - 1] =
operator(newTokens[newTokens.length - 1], token);
operator = null;
} else {
newTokens.push(token);
}
}
tokens = newTokens;
}
if (tokens.length > 1) {
console.log('Error: unable to resolve calculation');
return tokens;
} else {
return tokens[0];
}
}
const userInput = document.getElementById('userInput');
userInput.focus();
userInput.addEventListener('input', function() {
document.getElementById('result').innerHTML = "The answer is " + calculate(tokenize(userInput.value));
});
<input type="text" id="userInput" />
<div id="result"></div>
(Alternative version here). To allow parentheses, you could tell the calculate
function to check for parentheses before it starts looking for any of the other operators, then recursively call itself on the expression within each set of parentheses. The parsing function can also be improved e.g. removing any white space and dealing with errors.
calculate("1 + 2 / 9")
– Jabari King Commented Aug 30, 2015 at 1:461+3*5-10%
, the script process would evaluate 1+3, and store it, then 5*5, store it, then 25-10, store it, then output 0.15. – spb Commented Aug 30, 2015 at 2:04