package com.coding.basic.stack.expr; import java.util.ArrayList; import java.util.List; import java.util.Stack; import com.coding.basic.stack.StackUtil; public class InfixExpr { String expr = null; private List<Token> tokenList = new ArrayList<>(); private final static String regex = "-|\\+|\\*|/|\\(|\\)"; public InfixExpr(String expr) { this.expr = expr; init(); } private void init() { if (StackUtil.isValidPairs(expr)) { initTokens(); } else { throw new RuntimeException( "Syntax error, ( ) is not completed in your Expression"); } } /** * 表达式分解并入栈 */ private void initTokens() { String[] nums = expr.split(regex); ArrayList<String> arrayList = new ArrayList<String>(); for (int i = 0; i < nums.length; i++) { if (!nums[i].equals("")) { arrayList.add(nums[i]); } } char[] exChars = expr.toCharArray(); int numInx = 0; for (int i = 0; i < exChars.length;) { char ex = exChars[i]; int item = ex & 0xffff; if (item >= 48 && item <= 57) { int numSize = arrayList.get(numInx++).length(); String num = new String(exChars, i, numSize); Token token = new Token(num, Token.NUMBER); tokenList.add(token); i += numSize; } else { Token token = new Token(String.valueOf(ex), Token.OPERA); tokenList.add(token); i += 1; } } } /** * 从左向右扫描所有token,当遇到同优先级或低优先级的操作符时,把之前的操作符依次出栈并计算结果 * 扫描完所有token后,依次出栈所有操作数并计算结果 * * @return */ public float evaluate() { Stack<Token> opStack = new Stack<>(); Stack<Float> numStack = new Stack<>(); for (int i = 0; i < tokenList.size(); i++) { Token token = tokenList.get(i); switch (token.getType()) { case Token.NUMBER: numStack.push(token.getNumValue()); break; case Token.OPERA: if (opStack.isEmpty()) { opStack.push(token); } else { while (!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())) { Token preOper = opStack.pop(); Float latter = numStack.pop(); Float former = numStack.pop(); Float result = caculate(preOper, latter, former); numStack.push(result); } opStack.push(token); } break; default: throw new RuntimeException(" error not Number not Operate "); } } while (!opStack.isEmpty()) { Token pre = opStack.pop(); Float f1 = numStack.pop(); Float f2 = numStack.pop(); Float result = caculate(pre, f1, f2); numStack.push(result); } return numStack.pop(); } private Float caculate(Token t, Float latter,Float former){ switch (t.getValue()) { case "+": return latter + former; case "-": return former - latter; case "*": return latter * former; case "/": return former / latter; default: throw new RuntimeException("operation"+t.getValue()+" isn't implemented"); } } }