• 中缀表达式解析求值


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

    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;
    	}
    }
    
  • 相关阅读:
    Python字典处理技巧
    javascript常用对象
    8. 异步操作
    九度OnlineJudge之1022:游船出租
    直方图(下)
    MySQL中关于日期、时间的数据类型和函数
    libvirt(virsh命令介绍)
    11g的alert日志路径
    使用GridView来获取xml文件数据
    MediaPlayer视频播放器
  • 原文地址:https://www.cnblogs.com/mosmith/p/6388533.html
Copyright © 2020-2023  润新知