`
leichenlei
  • 浏览: 125339 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

简单的表达式、公式解析器

 
阅读更多

最近在做新项目,需要计算预先配置的表达式的结果。

表达式特点:

1,浮点类型

2,代变量参数

3,只限于简单计算符号

表达式类似于:"3*(4+a)/6"

程序:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * 
 * @author chenlei
 * @2013-1-16
 */
public class Formula {
	/**
	 * 类型
	 */
	private final static int NUMBER = 1;
	private final static int OPERATOR = 2;
	private final static int END_PAREN = 3;
	private final static int START_PAREN = 4;
	/**
	 * 操作符优先级
	 */
	private static Map<Character, Integer> priority;
	static{
		priority = new HashMap<Character, Integer>(4);
		priority.put('-', 1);
		priority.put('+', 1);
		priority.put('*', 2);
		priority.put('/', 2);
	}
	/**
	 * 后缀表达式
	 */
	public List<String> postfix = new ArrayList<String>();
	/**
	 * 构造
	 * @param formula 公式
	 */
	public Formula(String formula){
		formula = formula.toLowerCase();
		LinkedList<Character> stack = new LinkedList<Character>();
		int type = 0;
		StringBuffer str= new StringBuffer();
		for(int i = 0; i < formula.length(); i++){
			char c = formula.charAt(i);
			if(c >= 48 && c <= 57  || c >= 97 && c <= 122 || c == 46){
				type = NUMBER;
				str.append(c);
			}else{
				if(str.length() != 0){
					postfix.add(str.toString());
					str.setLength(0);
				}
				switch(c){
					case '+':
					case '-':
					case '*':
					case '/':
						if(type == 0 || type == OPERATOR || type == START_PAREN){
							throw new RuntimeException("format error !");
						}
						type = OPERATOR;
						operator(stack, c);
					break;
					case '(':
						type = START_PAREN;
						stack.push(c);
					break;
					case ')':
						if(type == OPERATOR){
							throw new RuntimeException("format error !");
						}
						type = END_PAREN;
						endParen(stack);
					break;
				}
			}
		}
		if(str.length() != 0){
			postfix.add(str.toString());
		}
		while(!stack.isEmpty()){
			char operator = stack.pop();
			if(operator == '('){
				throw new RuntimeException("paren not paired !");
			}
			postfix.add(operator + "");
		}
	}
	/**
	 * 公式结果
	 * @param variable 公式变量
	 * @return 结果
	 */
	public double getResult(double... variable){
		LinkedList<Double> stack = new LinkedList<Double>();
		int varIndex = 0;
		for(String element : postfix){
			char c = element.charAt(0);
			if(c >= 48 && c <= 57 || c == 46){
				stack.push(Double.parseDouble(element));
			}else if(c >= 97 && c <= 122){
				stack.push(variable[varIndex]);
				varIndex++;
			}else{
				double num2 = stack.pop();
				double num1 = stack.pop();
				double num;
				switch(c){
					case '+':
						num = num1 + num2;
					break;
					case '-':
						num = num1 - num2;
					break;
					case '*':
						num = num1 * num2;
					break;
					case '/':
						num = num1 / num2;
					break;
					default:
						num = 0;
				}
				stack.push(num);
			}
		}
		if(stack.size() == 0){
			return 0;
		}else{
			return stack.pop();
		}
	}
	/**
	 * 处理操作符
	 * @param operator 操作符
	 */
	private void operator(LinkedList<Character> stack, char operator){
		int prior = priority.get(operator);
		while(!stack.isEmpty()){
			char thisOperater = stack.pop();
			if(thisOperater == '('){
				stack.push(thisOperater);
				break;
			}else{
				int thisPrior = priority.get(thisOperater);
				if(thisPrior < prior){
					stack.push(thisOperater);
					break;
				}else{
					postfix.add(thisOperater + "");
				}
			}
		}
		stack.push(operator);
	}
	/**
	 * 处理结束括号
	 */
	private void endParen(LinkedList<Character> stack){
		boolean startParen = false;
		while(!stack.isEmpty()){
			char element = stack.pop();
			if(element == '('){
				startParen = true;
				break;
			}else{
				postfix.add(element + "");
			}
		}
		if(startParen == false){
			throw new RuntimeException("paren not paired !");
		}
	}
	public static void main(String[] args) {
		Formula formula = new Formula("3*(4+a)/6");
		System.out.println(formula.getResult(5));
	}
}

 

参考了java数据结构和算法 第二版。但,加入了错误处理、变量等。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics