最近在做新项目,需要计算预先配置的表达式的结果。
表达式特点:
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数据结构和算法 第二版。但,加入了错误处理、变量等。