中缀表达式解析求值

今天在技术交流群里面碰到一个菜鸡,问关于表达式解析求值的问题,数据结构的书中一般都有这个的介绍,但一般都是前缀和后缀的表达式的方法,于是想试试自然一点的方法。

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;
	}
}
原文地址:https://www.cnblogs.com/mosmith/p/6388533.html