Expression evaluation (infix expression) - java version

Posted by euph on Sun, 04 Aug 2019 07:49:37 +0200

_infix expression is a general expression method of arithmetic or logic formula, which conforms to the thinking of human routine calculation. The realization method of expression evaluation is a typical application of stack.
In computer, any expression is composed of operands, operators and boundaries. In this paper, we only discuss operations of integer, brackets, addition, subtraction, multiplication and division, remainder and square.
According to the four rules of operation:

    (1) First in brackets, then out of brackets
    (2) Square first, multiply and divide the remainder, then add and subtract
    (3) Peer operations from left to right

For example: {5*3^2+[7+(5-2)]}*3. This example can be ignored first. Look at the following ideas first, and then come back to the example to do the experiment.
_Sets the priority of each operator according to the operation rules:

              '+','-':  0
          '*','/','%':  1
                  '^':  2
             '[',']':  -1
             '(',')':  -3
             '{','}':  -2    

Computing process stack change table:

Serial number Operator stack Operator stack Notes
0 { Encountering left parentheses directly into the stack
1 5 { Encountering operands directly into the stack
2 5 { * Current high-priority stacking
3 5 3 { * Operator
4 5 3 { * ^ High priority stacking
5 5 3 2 { * ^ /
6 5 9 { * Current pointing symbol priority is small, do calculation
6 45 { + Low priority, high computing/priority, stacking
7 45 { + [ Left bracket stacking
8 45 7 { + [ /
9 45 7 { + [ + High priority stacking
10 45 7 { + [ + ( Left bracket stacking
11 45 7 5 { + [ + ( /
12 45 7 5 { + [ + ( - High priority stacking
13 45 7 5 2 { + [ + ( - /
14 45 7 3 { + [ + Encounter right bracket calculation
15 45 10 { Encounter right bracket calculation
16 55 Encounter right bracket calculation
17 55 * /
18 55 3 * /
19 165

The final result is 165.

Solutions:

index refers to where the expression string is currently traversed

  1. If it is left bracket, it goes directly into the symbol stack. This operation matches the right bracket for later traversal.
//            If you enter the stack directly for the left parentheses
            if (isLeft(s.charAt(index))) {
                operS.push(s.charAt(index));
                index++;
            }
  1. If the current pointing element is a number, consider whether it is a multi-digit number, so you need to keep looking backwards until you point to a symbol or to the last bit of the expression, then stop. Put the number into the operand stack.
//            If the element is a number
            String number = "";
//    This element is not a parenthesis, not an operator, but a number, which is considered in this article.
            while (!isOper(s.charAt(index)) && !isLeft(s.charAt(index)) && !isRight(s.charAt(index))) {
                number += s.charAt(index);
// In order to prevent the number from reaching the last position of the expression, it is necessary to judge. Otherwise, it will go into a dead cycle.
                if (index == s.length() - 1) break;
                index++;
            }
            if (number != "") {
                numS.push(Integer.parseInt(number));
            }

  1. If the current pointer is an operator, the following situations should be considered:
    A. Current pointing operator priority <= symbol stack top symbol priority: need to pop up two numbers from the operand stack, symbol stack pop up a symbol, operation, operation resu lt s into the operand stack.
    b. Current Pointing Operator Priority > Top Priority of Symbol Stack: Pressed directly into the Stack
    c: Additional consideration 1: If the current point points to the last bit of the expression, and this one happens to be a number, and at this time, the symbol stack is not empty, and need to be calculated, so consider that when pointing to the last bit, you can also enter the discussion. After a calculation, the symbol stack is empty and exits.
    d: Additional consideration 2: Since the input may accidentally input two or more operators in succession, after index ++, it is also necessary to consider whether this means an operator, and if so, the expression input is incorrect.
//            If the element is an operator
            int num1, num2, oper, res;
//             When the formula reaches the last place, it has to be calculated once before it is finished.
            if (isOper(s.charAt(index)) || index == s.length() - 1) {
//                If the symbol stack is empty, the element goes directly to the stack
                while (!operS.isEmpty() &&
                        operS.priority(s.charAt(index)) <= operS.priority(operS.peek()) || !isOper(s.charAt(index))&&!isLeft(s.charAt(index)) && !isRight(s.charAt(index))) {
                    if (operS.isEmpty()) break;
                    num1 = numS.pop();
                    num2 = numS.pop();
                    oper = operS.pop();
                    res = campute(num1, num2, oper);
                    numS.push(res);

                }

//       The last digit is the number to prevent him from entering the symbol stack, so a judgment is needed.
                if (isOper(s.charAt(index))) {
                    operS.push(s.charAt(index));
                    index++;
                    if (isOper(s.charAt(index))) {
                        System.out.println("Continuous computational symbols, errors");
                        return 99999;
                    }
                }


            }
  1. If the current point is to the right parentheses. At this time, the expression in parentheses should be calculated first, so the stack operation should be performed at this time. During the operation, the left parentheses stop operation. If the left parentheses encounter the same priority as the current right parentheses, then the matching of brackets is successful, the left parentheses are out of the stack, and index++ goes beyond the current right parentheses. Number, continue with the operation.
    Additionally, considering the possible shortage of parentheses or mismatching, we first determine whether the symbol stack is empty when the right parentheses are used.
//If the element is in right parentheses
            if (isRight(s.charAt(index)) && !operS.isEmpty()) {
                while (!isLeft(operS.peek())) {
                    num1 = numS.pop();
                    num2 = numS.pop();
                    oper = operS.pop();
                    res = campute(num1, num2, oper);
                    numS.push(res);
                }
                if (operS.priority(s.charAt(index)) == operS.priority(operS.peek())) {
                    operS.pop();  //The left bracket at the top of the pop-up stack
                    index++; //Next bit crosses the current right bracket
                } else {
                    System.out.println("Bracket matching error");
                    return 99999;
                }
            }
  1. true loop termination condition
//            The calculation ends when the symbol stack is empty and the expression has reached the end.
            if (operS.isEmpty() && index == s.length() - 1) break;

  1. Result
// The last number left in the stack is the final result.
        return numS.pop();

Complete procedures, you can modify their own simpler

public class CamputeStackDemo {
    public static void main(String[] args) {
        String s = "{5^2%3^2+[7+(5+2)]*3}*2";
        int i = doCamputee(s);
        System.out.println(i);
    }
    /**
     *  subject
     * @param s   Formula
     * @return  Final results
     */
    public static int doCamputee(String s) {
        int index = 0; // Index of strings
//        Create two stacks
        CamputeStack numS = new CamputeStack(50); // Digital stack
        CamputeStack operS = new CamputeStack(50); //Symbol stack
        while (true) {
//            If you enter the stack directly for the left parentheses
            if (isLeft(s.charAt(index))) {
                operS.push(s.charAt(index));
                index++;
            }
//            If the element is a number
            String number = "";
            while (!isOper(s.charAt(index)) && !isLeft(s.charAt(index)) && !isRight(s.charAt(index))) {
                number += s.charAt(index);
                if (index == s.length() - 1) break;
                index++;
            }
            if (number != "") {
                numS.push(Integer.parseInt(number));
            }
//            If the element is a computational symbol
            int num1, num2, oper, res;
//             When the formula reaches the last place, it has to be calculated once before it is finished.
            if (isOper(s.charAt(index)) || index == s.length() - 1) {
//                If the symbol stack is empty, the element goes directly to the stack
                while (!operS.isEmpty() &&
                        operS.priority(s.charAt(index)) <= operS.priority(operS.peek()) || !isOper(s.charAt(index))) {
                    if (operS.isEmpty()) break;
                    num1 = numS.pop();
                    num2 = numS.pop();
                    oper = operS.pop();
                    res = campute(num1, num2, oper);
                    numS.push(res);
                }

//       The last digit is the number to prevent him from entering the symbol stack, so a judgment is needed.
                if (isOper(s.charAt(index))) {
                    operS.push(s.charAt(index));
                    index++;
                    if (isOper(s.charAt(index))) {
                        System.out.println("Continuous computational symbols, errors");
                        return 99999;
                    }
                }
            }
//If the element is in right parentheses
            if (isRight(s.charAt(index)) && !operS.isEmpty()) {
                while (!isLeft(operS.peek())) {
                    num1 = numS.pop();
                    num2 = numS.pop();
                    oper = operS.pop();
                    res = campute(num1, num2, oper);
                    numS.push(res);
                }
                if (operS.priority(s.charAt(index)) == operS.priority(operS.peek())) {
                    operS.pop();  //The left bracket at the top of the pop-up stack
                    index++; //Next bit crosses the current right bracket
                } else {
                    System.out.println("Bracket matching error");
                    return 99999;
                }
            }
//            The calculation ends when the symbol stack is empty and the expression has reached the end.
            if (operS.isEmpty() && index == s.length() - 1) break;

        }
// The last number left in the stack is the final result.
        return numS.pop();
    }


    //    Determine whether an element is a number or a symbol
    public static boolean isOper(char v) {
        if (v == '+' || v == '-' || v == '*' || v == '/' || v=='%' || v=='^') return true;
        return false;
    }
    // Judge whether it's left bracket
    public static boolean isLeft(int v) {
       if(v== '(' || v=='[' || v=='{') return true;
       return false;
    }
    //    Judge whether it's a right bracket
    public static boolean isRight(int v) {
        if (v == ')' || v == ']' || v == '}') return true;
        return false;
    }

    //    The result of calculating two numbers
    public static int campute(int num1, int num2, int oper) {
        int var = 0;
        switch (oper) {
            case '+': {
                var = num1 + num2;
                break;
            }
            case '-': {
                var = num2 - num1;
                break;
            }
            case '*': {
                var = num2 * num1;
                break;
            }
            case '/': {
                var = num2 / num1;
                break;
            }
            case '%':{
                var = num2%num1;
                break;
            }
            case '^':{
                var = 1;
                for(int i = 1 ; i <= num1 ; i++){
                    var *=num2;
                }
                break;
            }
            default: {
                System.out.println("The symbol is incorrect.");
                break;
            }
        }
        return var;
    }
}

//  Establishment of stack
class CamputeStack {
    private int maxSize; // Stack size
    private int[] stack; //Stack
    private int top = -1; //Define the top of the stack


    //    Initialization stack
    public CamputeStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }
    //    Determine whether the stack is empty
    public boolean isEmpty() {
        return top == -1;
    }
    //    Determine whether the stack is full
    public boolean isFull() {
        return top == maxSize - 1;
    }
    //    Push
    public void push(int v) {
        if (isFull()) {
            System.out.println("Stack full");
            return;
        }
        top++;
        stack[top] = v;
    }
    //    Stack out
    public int pop() {
        if (isEmpty()) {
            System.out.println("Stack space");
            throw new RuntimeException("Stack space");
        }
        int v = stack[top];
        top--;
        return v;
    }

    //    View stack top elements
    public int peek() {
        if (isEmpty()) {
            System.out.println("Stack space");
            throw new RuntimeException("Stack space");
        }
        return stack[top];
    }

    //    Returns the priority of the element
    public int priority(int oper) {
        int val = 100;
        switch (oper) {
            case '*':
            case '%':
            case '/': {
                val = 1;
                break;
            }
            case '^':{
                val = 2;
                break;
            }
            case '+':
            case '-': {
                val = 0;
                break;
            }
            case '[':
            case ']': {
                val = -1;
                break;
            }
            case '{':
            case '}': {
                val = -2;
                break;
            }
            case '(':
            case ')': {
                val = -3;
                break;
            }

        }
        return val;
    }


}

This is the end of this article. Everyone has a good life --- Bat!!!