Equation (expression) parser with precedence?

前端 未结 23 1908
遇见更好的自我
遇见更好的自我 2020-11-22 11:44

I\'ve developed an equation parser using a simple stack algorithm that will handle binary (+, -, |, &, *, /, etc) operators, unary (!) operators, and parenthesis.

<
23条回答
  •  暗喜
    暗喜 (楼主)
    2020-11-22 12:17

    Actually there's a way to do this without recursion, which allows you to go through the entire expression once, character by character. This is O(n) for time and space. It takes all of 5 milliseconds to run even for a medium-sized expression.

    First, you'd want to do a check to ensure that your parens are balanced. I'm not doing it here for simplicity. Also, I'm acting as if this were a calculator. Calculators do not apply precedence unless you wrap an expression in parens.

    I'm using two stacks, one for the operands and another for the operators. I increase the priority of the operation whenever I reach an opening '(' paren and decrease the priority whenever I reach a closing ')' paren. I've even revised the code to add in numbers with decimals. This is in c#.

    NOTE: This doesn't work for signed numbers like negative numbers. Probably is just a simple revision.

      internal double Compute(string sequence)
        {
            int priority = 0;
            int sequenceCount = sequence.Length;            
            for (int i = 0; i < sequenceCount; i++) {
                char s = sequence[i];                
                if (Char.IsDigit(s)) {
                    double value = ParseNextNumber(sequence, i);
                    numberStack.Push(value);
                    i = i + value.ToString().Length - 1;
                } else if (s == '+' || s == '-' || s == '*' || s == '/')  {                
                   Operator op = ParseNextOperator(sequence, i, priority);
                    CollapseTop(op, numberStack, operatorStack);
                    operatorStack.Push(op);
                } if (s == '(') { priority++; ; continue; }
                else if (s == ')') { priority--; continue; }
            }
            if (priority != 0) { throw new ApplicationException("Parens not balanced"); }
            CollapseTop(new Operator(' ', 0), numberStack, operatorStack);
            if (numberStack.Count == 1 && operatorStack.Count == 0) {
                return numberStack.Pop();
            }
            return 0;
        }    
    

    Then to test this out:

    Calculator c = new Calculator();
    double value = c.Compute("89.8+((9*3)+8)+(9*2)+1");
    Console.WriteLine(string.Format("The sum of the expression is: {0}", (float)value));
    //prints out The sum of the expression is: 143.8
    

提交回复
热议问题