最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

logic - How to code a calculator in JavaScript without 'eval' - Stack Overflow

programmeradmin0浏览0评论

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 How are you gonna use the calculator? Do you want like a main calculator function and you pass expressions as strings to it? Like this: calculate("1 + 2 / 9") – Jabari King Commented Aug 30, 2015 at 1:46
  • 1 i'll take whatever works, at this point. it wasn't my intention because i thought evaluating at the end like that, with all of the operators might be even more of a pain, since i'd have to account for order of operations, but if you know of a way, i'd love if you'd share. i had it in mind to do something such that if a user entered 1+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
  • 1 Yes. There would have to be some sort of logic to know where to split up the expression though. – Jabari King Commented Aug 30, 2015 at 2:05
  • 2 A similar question on StackOverflow, but with more answers, is available here. – Erik Vullings Commented Jan 4, 2021 at 16:53
Add a comment  | 

1 Answer 1

Reset to default 15

For 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.

发布评论

评论列表(0)

  1. 暂无评论