Java后缀表达式实现表达式求值

package com.djb.calculatdemo;

import java.util.ArrayList;
import java.util.Stack;

import javax.management.RuntimeErrorException;

public class CalculatTest {
    public static void main(String[] args) {
        ArrayList suffixfxpression = getSuffixfxpression("10.5+((2+3)*4)-5/2");
        double calculate = calculate(suffixfxpression);
        System.out.println(calculate);
    }

    /**
     * 将中缀表达式字符串转成后缀表达式数组
     * @param str 传入的中缀表达式字符串
     * @return 后缀表达式数组
     */
    private static ArrayList getSuffixfxpression(String str){
        //保存运算符号的栈
        Stack signStack = new Stack();
        //保存后缀表达式的数组
        ArrayList numList = new ArrayList();
        //保存当前遍历到的数字
        StringBuffer curNum = new StringBuffer();

        for (int i = 0; i < str.length(); i++) {
            //当前遍历的字符
            char ch = str.charAt(i);
            if (ch >= 48 && ch <= 57 || ch == '.') {//遍历到是数字
                curNum.append(ch);
                //获取一个完整的数字
                int j = i + 1;
                while (true) {
                    if (j == str.length()) {
                        break;
                    }
                    
                    if (str.charAt(j) >= 48 && str.charAt(j) <= 57 || str.charAt(j) == '.') {
                        curNum.append(str.charAt(j));
                    }else {
                        break;
                    }
                    
                    j ++;
                }
                
                //将获取到的完整数字放入数组中
                numList.add(curNum.toString());
                //清空当前拼接的数字
                curNum.delete(0, curNum.length());
                i = j - 1;
                
            }else if (ch == '(') {//遍历到左括号直接入符号栈
                signStack.push(String.valueOf(ch));
            }else if (ch == ')') {//遍历到右括号,将符号栈的符号依次加入到数组数组中,知道碰到左括号,再将左括号出栈
                while (!signStack.peek().equals("(")) {
                    numList.add(signStack.pop());
                }
                signStack.pop();
            }else {//遍历到运算符号时,如果当前运算符号优先级低于符号栈顶的优先级,将符号栈栈顶出栈加入到数字数字中,知道当前符号高于栈顶的优先级
                while (signStack.size() > 0 && getSymbolGread(signStack.peek()) >= getSymbolGread(String.valueOf(ch))) {
                    numList.add(signStack.pop());
                }
                //最后将当前符号入栈
                signStack.push(String.valueOf(ch));
            }
            
        }
        //将符号栈的数据依次出栈加入到数字数组中
        while (signStack.size() > 0) {
            numList.add(signStack.pop());
            
        }
        return numList;
    }
    
    /**
     * 根据后缀表达式计算结果
     * @param array 后缀表达式的数组
     */
    private static double calculate(ArrayList array) {
        Stack numStack = new Stack();
        //正序遍历后缀表达式数组
        for (String item : array) {
            if (isSymbol(item)) {//遍历到运算符,顺序在栈中取出两个数,然后逆向让两个数运算,将运算的结果入栈
                double result = 0;
                double num1 = Double.parseDouble(numStack.pop());
                double num2 = Double.parseDouble(numStack.pop());
                if (item.equals("+")) {
                    result = num2 + num1;
                }else if (item.equals("-")) {
                    result = num2 - num1;
                }else if (item.equals("*")) {
                    result = num2 * num1;
                }else if (item.equals("/")) {
                    result = num2 / num1;
                }else {
                    throw new RuntimeErrorException(null, "非法的运算符");
                }
                numStack.push(String.valueOf(result));
            }else {//遍历到数字,直接入栈
                numStack.push(item);
            }
        }
        //最后出栈的就是计算的结果
        return Double.parseDouble(numStack.pop());
    }
    
    /**
     * 获取运算符号的优先级
     * @param symbol 传入的运算符号
     */
    private static int getSymbolGread(String symbol){
        int gread = 0;
        switch (symbol) {
        case "+":
        case "-":
            gread = 1;
            break;
        case "*":
        case "/":
            gread = 2;
        default:
            break;
        }
        return gread;
    }
    
    /**
     * 判断传入的字符串是否为运算符号
     * @param str 传入的字符串
     */
    private static boolean isSymbol(String str) {
        return str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/");
    }
    
}



你可能感兴趣的:(Java后缀表达式实现表达式求值)