如何让计算机计算算数表达式

2023-03-04  本文已影响0人  放开那个BUG

1、前言

如果计算一个表达式:5 * (2 + 8 / 4) + 6,作为人类我们能很快利用符号的优先级进行计算。但是对于计算机来说,它并不能很好的识别这个算式,我们要把它转换成计算机可以方便识别的模式。针对于 5 * (2 + 8 / 4) + 6,它叫做中缀表达式。而计算机容易识别的表达式叫后缀表达式:5284/+*6+。然后就很方便的计算后缀表达式了。

2、转换与计算算法

转换主要靠栈,转换的算法流程:
1)从左到右进行遍历
2)遇到操作数直接输出(即收集起来)
3)遇到左括号直接入栈,括号是最高优先级。但是一旦入栈,需要把它的优先级将到最低,确保其他符号能正确入栈。
4)遇到右括号,说明括号已经结束。不断出栈,直到遇到左括号(左括号不输出)
5)遇到其它运算符,则比较该运算符与栈顶运算符的优先级,如果优先级大于栈顶优先级则直接入栈;否则出栈到小于等于该运算符
6)如果对象处理完毕,则按顺序弹出并输出栈中所有运算符

那么针对于上述表达式:5 * (2 + 8 / 4) + 6,代码如下:

public class Translate {

    public String translate(String original){
        if(original == null || original.length() == 0){
            return null;
        }
        Stack<Character> stack = new Stack<>();
        StringBuilder builder = new StringBuilder();
        Map<Character, Integer> map = new HashMap<>();
        map.put('(', 1);
        map.put('+', 2);
        map.put('-', 2);
        map.put('*', 3);
        map.put('/', 3);

        for (char ch : original.toCharArray()) {
            if(ch >= '0' && ch <= '9'){
                builder.append(ch);
            }else if(ch == '('){
                stack.push(ch);
            }else if(ch == '+' || ch == '-' || ch == '*' || ch == '/'){
                while(!stack.isEmpty() && map.get(ch) <= map.get(stack.peek())){
                    builder.append(stack.pop());
                }
                stack.push(ch);
            }else if(ch == ')'){
                while(stack.peek() != '('){
                    builder.append(stack.pop());
                }
                stack.pop();
            }
        }
        while (!stack.isEmpty()){
            builder.append(stack.pop());
        }
        return builder.toString();
    }

    public static void main(String[] args) {
        System.out.println(new Translate().translate("5*(2+8/4)+6"));
    }
}

计算算法就比较简单了:
1)遍历后缀表达式,如果遇到数字,则直接入栈;如果遇到字符则计算,并将结果入栈,一直到遍历结束。

那么对于已经变成后缀表达式的:5284/+*6+,计算代码如下:

public class Translate {

    public int calculate(String original){
        Stack<Integer> stack = new Stack<>();
        for(char ch : original.toCharArray()){
            if(ch == '+' || ch == '-' || ch == '*' || ch == '/'){
                int num1 = stack.pop(), num2 = stack.pop();
                if(ch == '+'){
                    stack.push(num2 + num1);
                }
                if(ch == '-'){
                    stack.push(num2 - num1);
                }
                if(ch == '*'){
                    stack.push(num2 * num1);
                }
                if(ch == '/'){
                    stack.push(num2 / num1);
                }
            }else{
                stack.push(ch - '0');
            }
        }

        return stack.pop();
    }

    public static void main(String[] args) {
        System.out.println(new Translate().calculate("5*(2+8/4)+6"));
    }
}

3、后记

当然,这个表达式还未考虑各种异常情况,或者数是负数的情况,或者数不是个位的情况,如果有兴趣可以参加 leetcode 的 224 题。

上一篇 下一篇

猜你喜欢

热点阅读