数学表达式解析工具类:
支持负数运算,
多层括号嵌套运算
采用堆栈实现,实现步骤:
(1)除去表达式中所有空白
(2)提取表达式运算符合
(3)依据运算符合,将表达式转化为一个数组
(4)对这个数组进行数学运算优先级转化,生成一个新数组的
(5)最后对这个数组进行运算,得到结果
注:具体算法细节请查看代码。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package autotest.entity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Pattern;
import autotest.util.StringUtils;
/**
* 支持加减乘法运算
* @author Administrator
*/
public class ExpressionResolver {
private final static Map<String,Integer> SERT=new HashMap<String,Integer>();
static{
SERT.put("+", 1);
SERT.put("-", 1);
SERT.put("*", 2);
SERT.put("/", 2);
SERT.put("(", 3);
SERT.put(")", 3);
}
/**
* 转换有负号表达式-3+2 转换为 (0-3)+2
* 2-3不转
* (-3)+2 ==>((0-3))+2
* @param exp
* @return
*/
private static String transfrom(String exp){
exp=StringUtils.trimAllSpace(exp);
return exp.replaceAll("(\\(|^)-(\\d*)", "$1(0-$2)");
}
/**
* 解析表达式
* @param exp
* @return
*/
private static List<String> resolveExpr(String exp){
String opert=exp.replaceAll("\\d*", "");
List<String> list=new ArrayList<String>();
int pidx=-1;
for(int i=0;i<opert.length();i++){
String p=opert.substring(i, i+1);
pidx=exp.indexOf(p);
if(exp.substring(0,pidx).trim().length()!=0){
list.add(exp.substring(0, pidx));
}
list.add(exp.substring(pidx, pidx+1));
exp=exp.substring(pidx+1);
}
if(exp.length()>0){
list.add(exp);
}
return list;
}
/**
* 转为计算机可以识别的表达式
* @param list
* @return
*/
private static String[] transfrom(List<String> list){
Stack<Sign> op=new Stack<Sign>();
Stack<String> data=new Stack<String>();
Iterator<String> it=list.iterator();
int p1=0,p2=0,add=0;
while(it.hasNext()){
String e=it.next();
if(SERT.containsKey(e)){
if(op.size()>0){
p1=op.peek().getWeight();
}
p2=SERT.get(e)+add;
if(e.equals("(")){
add+=SERT.get(e);
continue;
}
if(e.equals(")")){
add-=SERT.get(e);
continue;
}
while(p2<=p1){
data.push(op.pop().getSign());
if(op.size()==0){
break;
}
p1=op.peek().getWeight();
}
op.push(new Sign(e,p2));
}else{
data.push(e);
}
}
while(op.size()>0){
data.push(op.pop().getSign());
}
String[] result=new String[data.size()];
for(int i=0;i<result.length;i++){
result[result.length-i-1]=data.pop();
}
return result;
}
/**
* 计算表达式值
* @param exp
* @param duckSqls
* @return
*/
public static Object getExp(String exp,List<DuckSQL> duckSqls)throws Exception{
// if(!StringUtils.isValidateStr(exp) || duckSqls==null || duckSqls.size()<=0){
// return null;
// }
exp=transfrom(exp);
String[] strs=transfrom(resolveExpr(exp));
Stack<Object> expstack=new Stack<Object>();
for(int i=0;i<strs.length;i++){
String str=strs[i];
if(SERT.containsKey(str)){
expstack.push(calc(expstack.pop(),expstack.pop(),str,duckSqls));
}else{
expstack.push(str);
}
}
if(expstack.size()==1){
return expstack.pop();
}else{
return "ERR";
}
}
/**
* 计算结果
* @param s1
* @param s2
* @param op
* @return
*/
private static Object calc(Object s1,Object s2,String op,List<DuckSQL> duckSqls)throws Exception{
Double d1=null,d2=null;
if(s1 instanceof String){
d1=Double.parseDouble((String)s1);//getValue((String)s1,duckSqls);
}else{
d1=(Double)s1;;
}
if(s2 instanceof String){
d2=Double.parseDouble((String)s2);;
}else{
d2=(Double)s2;
}
if(op.equals("-")){
return d2-d1;
}else if(op.equals("+")){
return d2+d1;
}else if(op.equals("*")){
return d2*d1;
}else if(op.equals("/")){
return d2/d1;
}else{
throw new Exception("表达式中运算符["+op+"]是不合法的");
}
}
private static Double getValue(String str,List<DuckSQL> duckSqls)throws Exception{
if(!Pattern.matches("\\d{2}", str)){
throw new Exception("表达式中含有不合法的式子["+str+"]");
}
Object obj = duckSqls.get(Integer.parseInt(str.substring(0, 1))-1).getRsdata()[Integer.parseInt(str.substring(1, 2))-1];
if(obj instanceof Number){
return ((Number)obj).doubleValue();
}else{
throw new Exception("["+str+"]式子对应结果不是数据类型不可以加减乘法运算");
}
}
public static void main(String[] args)throws Exception{
// List<String> list=resolveExpr("(12+13)*14+15");
//
// String[] strs=transfrom(list);
// for(String str:strs){
// System.out.println(str);
// }
System.out.println(getExp("-3+2*(-5)+6+(-4)*7*(-9)*(2-3)",null));
// System.out.println("-3+2*(-5)+6+(-4)*7*(-9)*(2-3)".replaceAll("(\\(|^)-(\\d*)", "$1(0-$2)"));
}
}