今天在技术交流群里面碰到一个菜鸡,问关于表达式解析求值的问题,数据结构的书中一般都有这个的介绍,但一般都是前缀和后缀的表达式的方法,于是想试试自然一点的方法。
import java.util.Stack; public class Expression { public static void main(String[] args){ envaluate("3*8-12*(12*12/12/12)"); envaluate("4*5*20-12-30*12-(12*12/12/12)"); envaluate("4-5-5-7-8"); } public static void envaluate(String expression) { double result= new ExpressionReader(expression).envaluate(); System.out.println(String.format("%s=%s", expression,result)); } } class ExpressionReader { char[] expression; int pos = 0; public ExpressionReader(String _expression) { super(); this.expression = _expression.toCharArray(); } public boolean hasNext() { return pos<expression.length; } public char next() { return expression[pos++]; } public char peek() { return expression[pos]; } public double envaluate() { Stack<Double> args=new Stack<Double>(); Stack<Character> ops = new Stack<Character>(); while(hasNext()){ char c = peek(); if(c=='('){ next(); double value = envaluate(); args.push(value); }else if(c==')'){ next(); calculate(args,ops); return args.peek(); }else if(isOperator(c)){ next(); if(c=='+' || c=='-'){ if(ops.size()>=1){ calculate(args,ops); } } else if(c=='*' || c=='/'){ if(ops.size()>1){ char lastOp=ops.peek(); if(lastOp=='+' || lastOp=='-'){ }else { } } } ops.push(c); }else{ double value=readNumber(); args.push(value); } } calculate(args, ops); return args.peek(); } public double calculate(Stack<Double> args, Stack<Character> ops){ while(args.size()>=2 && ops.size()>=1){ double b=args.pop(); double a=args.pop(); char op=ops.pop(); if(!ops.isEmpty()){ char prevOp=ops.peek(); if(priority(op)==priority(prevOp)){ if(prevOp=='/'){ op=op=='*'?'/':'*'; }else if(prevOp=='-'){ op=op=='+'?'-':'+'; } } } double result = 0; switch(op){ case '+': result =a+b; break; case '-': result =a-b; break; case '*': result =a*b; break; case '/': result =a/b; break; } //System.out.println(String.format("%s%s%s=%s", a,op,b,result)); args.push(result); } return args.peek(); } public double readNumber() { double value=0; double rightPower=1; while(hasNext()){ char c=peek(); if(c=='.'){ next(); rightPower*=0.1; }else if(Character.isDigit(c)){ next(); if(rightPower>0) { value*=10; value +=(c-'0'); }else { value +=(c-'0') * rightPower; rightPower*=0.1; } }else { break; } } return value; } public static boolean isOperator(char c){ char[] operators={'+','-','*','/'}; for(char op:operators){ if(c==op){ return true; } } return false; } public static int priority(char op){ if(op=='+'|| op=='-'){ return 1; } return 2; } }