package stack; import java.util.Stack; /** * Created by Lanxiaowei * Craated on 2016/12/11 17:29 * 使用栈计算表达式值 */ public class EvaluateExpression { public static void main(String[] args) { String exp = "(1+2+3)*10-2*2-6*2"; int result = calculate(exp); System.out.println("result:" + result); } /** * 从指定位置开始获取表达式中的操作数 * @param exp 表达式 * @param pos 起始索引位置 * @return */ public static String getDigt(String exp,int pos) { if(!Character.isDigit(exp.charAt(pos))) { //如果获取到的是左括号,返回提取操作数失败 if(exp.charAt(pos) == '(') { return "false"; } throw new IllegalArgumentException("Invalid expression:" + exp); } int num = 0; while(pos < exp.length() && Character.isDigit(exp.charAt(pos))) { num = num * 10 + exp.charAt(pos++) - '0'; } return num + ""; } /** * 获取指定位置的操作符 * @param exp * @param pos * @return */ public static char getOper(String exp,int pos) { switch (exp.charAt(pos)) { case '+' : case '-' : case '*' : case '/' : case '(' : case ')' : return exp.charAt(pos); default: throw new IllegalArgumentException("Invalid expression:" + exp); } } /** * 获取运算符的优先级 * @param oper * @return */ public static OperatorLevel getOperatorLevel(char oper) { switch (oper) { case '+' : case '-' : return OperatorLevel.LOW; case '*' : case '/' : return OperatorLevel.HIGH; default: throw new IllegalArgumentException("Invalid Operator:" + oper); } } /** * 计算两个操作数的值 * @param leftNum * @param oper * @param rightNum * @return */ public static int opt(int leftNum,char oper,int rightNum) { int result = 0; switch (oper) { case '+' : result = leftNum + rightNum; break; case '-' : result = leftNum - rightNum; break; case '*' : result = leftNum * rightNum; break; case '/' : //除数为零的情况 if (rightNum == 0) { throw new IllegalArgumentException("The divisor MUST NOT be zero"); } else { result = leftNum / rightNum; } break; default: throw new IllegalArgumentException("Invalid Operator:" + oper); } return result; } /** * 比较两个操作符的优先级 * @param oper1 操作符1 * @param oper2 操作符2 * @return */ public static boolean isGreater(char oper1,char oper2) { return getOperatorLevel(oper1).getValue() > getOperatorLevel(oper2).getValue(); } /** * 计算表达式求值 * @param exp * @return */ public static int calculate(String exp) { if(null == exp || "".equals(exp)) { throw new IllegalArgumentException("Invalid expression:" + exp); } exp = exp.replace(" ", ""); exp = "(" + exp + ")"; //操作数栈 Stack<Integer> numStack = new Stack<Integer>(); //操作符栈 Stack<Character> operStack = new Stack<Character>(); int status = 0; int pos = 0; Integer tempNum = 0; char tempOper = '0'; char tempOper2 = '0'; int leftNum = 0; int rightNum = 0; String tem = ""; while (pos < exp.length()) { switch (status) { case 0: //提取操作数 //如果提取操作数不成功,则进入status=2步骤 tem = getDigt(exp, pos); if ("false".equals(tem)) { status = 2; break; } tempNum = Integer.valueOf(tem); //操作数压栈 numStack.push(tempNum); //进入步骤1 status = 1; pos = pos + tem.length(); break; case 1: //提取操作符 tempOper = getOper(exp,pos); //如果提取到的是左括号,则抛出异常 if(tempOper == '(') { throw new IllegalArgumentException("Invalid expression:" + exp); } //如果提取到的是右括号,则需要进行计算 if(tempOper == ')') { while (true) { //获取栈顶元素 tempOper = operStack.peek(); operStack.pop(); if(tempOper == '(') { break; } rightNum = numStack.pop(); leftNum = numStack.pop(); tempNum = opt(leftNum,tempOper,rightNum); numStack.push(tempNum); } status = 1; pos++; } else { if(operStack.empty()) { operStack.push(tempOper); status = 0; pos++; } else { tempOper2 = operStack.peek(); while (tempOper2 != '(' && !isGreater(tempOper,tempOper2)) { rightNum = numStack.pop(); leftNum = numStack.pop(); tempNum = opt(leftNum,tempOper2,rightNum); numStack.push(tempNum); operStack.pop(); if(operStack.empty()) { break; } tempOper2 = operStack.peek(); } operStack.push(tempOper); status = 0; pos++; } } break; case 2: //提取左括号( char oper = getOper(exp, pos); //如果获取到的不是左括号,则提示表达式输入不合法 if (oper != '(') { throw new IllegalArgumentException("Invalid expression:" + exp); } operStack.push(oper); //进入步骤0提取操作数,因为左括号后面紧跟的必须是操作数 status = 0; pos++; break; } } if(numStack.empty()) { throw new IllegalArgumentException("Invalid expression:" + exp); } tempNum = numStack.pop(); if(!numStack.empty()) { throw new IllegalArgumentException("Invalid expression:" + exp); } return tempNum; } }
使用栈计算表达式值
猜你喜欢
转载自iamyida.iteye.com/blog/2344309
今日推荐
周排行