最近由于公司需要做一个可以解析字符串为表达式进行公式计算的功能,所以上网找了一下,结果不是很满足需要,但是对其进行了一部分参考,用了两天时间写了一个公式解析类,如下:

jdk:1.5 /** *
package cn.yunhe.tools;
/**
*
Title: 公式解析类
*
Description: 实现对字符串表达式进行简单的包括函数的运算。
*
Copyright: Copyright (c) 2008
*
Company: HXYJ
* @author 幻想雨季(原创)
* @version 1.0
*/
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Gsjx {
public static Listlc = new ArrayList();//定义运算符
static{
lc.add("+"); lc.add("`"); lc.add("*"); lc.add("/");
}
public static Listlj = new ArrayList();//定义逻辑运算符
static{
lj.add(">"); lj.add(" }
public static MapfunMap = new HashMap();
// int数组注释,第一个标识:0自带函数 1自定义函数;第二个标识:参数个数
static{
//自带函数,可利用反射机制
funMap.put("abs", new int[]{0,1});  funMap.put("acos", new int[]{0,1});  funMap.put("asin", new int[]{0,1});
funMap.put("atan", new int[]{0,1});  funMap.put("cbrt", new int[]{0,1});  funMap.put("ceil", new int[]{0,1});
funMap.put("cos", new int[]{0,1});  funMap.put("cosh", new int[]{0,1});  funMap.put("exp", new int[]{0,1});
funMap.put("expm1", new int[]{0,1}); funMap.put("floor", new int[]{0,1}); funMap.put("log", new int[]{0,1});
funMap.put("log10", new int[]{0,1}); funMap.put("log1p", new int[]{0,1}); funMap.put("random", new int[]{0,1});
funMap.put("rint", new int[]{0,1});  funMap.put("round", new int[]{0,1}); funMap.put("signum", new int[]{0,1});
funMap.put("sin", new int[]{0,1});  funMap.put("sinh", new int[]{0,1});  funMap.put("sqrt", new int[]{0,1});
funMap.put("tan", new int[]{0,1});  funMap.put("tanh", new int[]{0,1});
funMap.put("max", new int[]{0,2});  funMap.put("min", new int[]{0,2});
//自定义函数
funMap.put("if", new int[]{1,3});  funMap.put("mod", new int[]{1,2});  funMap.put("int", new int[]{1,1});
}
/**
* 公式初始化转换
* @param str
* @return
*/
public static String strCast(String str) {
str = str.toLowerCase();//去除空格,变小写
if(str==null?true:str.length()==0)
return "0";
if(!checkFormula(str))return "0";
str = str.replaceAll("\\*-", "**");
str = str.replaceAll("-\\*", "**");
str = str.replaceAll("/-", "//");
str = str.replaceAll("-/", "//");
str = str.replaceAll("\\+-", "-");
str = str.replaceAll("-\\+", "-");
str = str.replaceAll("-", "`");
str = str.replaceAll("\\*\\*", "*-");
str = str.replaceAll("//", "/-");
str = str.replaceAll(" ", "");
return str;
}
/**
* 检查公式中括号出现次数是否正确
* @param formulaStr
* @return
*/
public static boolean checkFormula(String formulaStr) {
boolean flag = true;
int count = 0;
for (int i = 0; i < formulaStr.length(); i++) {
String s = String.valueOf(formulaStr.charAt(i));
if("(".equals(s))
count++;
else if(")".equals(s))
count--;
}
flag = count==0;
return flag;
}
/**
* 分割函数
* @param str
* @param bs
* @return
*/
public static String[] spliteFun(String str, String bs) {
Listlist = new ArrayList();
String bds = "";
int bracket = 0;
int len = str.length();
for (int i = 0; i < len; i++) {
String s = String.valueOf(str.charAt(i));
if("(".equals(s)) {
bracket++;
}else if(")".equals(s)) {
bracket--;
}
if(bracket==0 && bs.equals(s)) {
list.add(bds);
bds = "";
continue;
}
bds+=s;
}
list.add(bds);
String[] ss = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
ss[i] = list.get(i);
}
return ss;
}
/**
* 用户自定义函数
* @param str
* @param funStr
* @return
*/
public static String customFun(String str, String funStr) {
String reval = "0";
String[] gss = spliteFun(str, ",");
if("if".equals(funStr)) {
if(compare(gss[0])) {
reval = calculate(gss[1]);
}else{
reval = calculate(gss[2]);
}
}else if("mod".equals(funStr)) {
double d2 = new Double(calculate(gss[1]));
if(d2==0)return reval;
double d1 = new Double(calculate(gss[0]));
reval = (d1 % d2)+"";
}else if("int".equals(funStr)) {
reval = Math.floor(new Double(calculate(gss[0])))+"";
}
return reval;
}
//逻辑表达式判断
public static boolean compare(String str) {
boolean flag = false;
boolean bs = false;
int len = str.length();
int bracket = 0;
String ljbds = "";
double d_left = 0;
double d_right = 0;
for (int i = 0; i < len; i++) {
String s = String.valueOf(str.charAt(i));
if("(".equals(s)) {
bracket++;
}else if(")".equals(s)) {
bracket--;
}
if(bracket==0 && lj.contains(s)) {
for (int j = i; j < len; j++) {
String ts = String.valueOf(str.charAt(j));
if(lj.contains(ts)) {
ljbds+=ts;
}else{
bs=true;
break;
}
}
}
if(bs)break;
}
String[] s = str.split(ljbds);
d_left = new Double(calculate(s[0]));
d_right = new Double(calculate(s[1]));
if("   if(d_left}else if(">".equals(ljbds)) {
if(d_left>d_right)return true;
}else if("=".equals(ljbds)) {
if(d_left==d_right)return true;
}else if(">=".equals(ljbds)) {
if(d_left>=d_right)return true;
}else if("<=".equals(ljbds)) {
if(d_left<=d_right)return true;
}else if("<>".equals(ljbds) || "!=".equals(ljbds)) {
if(d_left!=d_right)return true;
}
return flag;
}
/**
* 递归调用运算
* @param str
* @return
*/
public static String calculate(String str) {
String reval = "";
String bds = "";
int bracket = 0;//对应括号个数
int pos = 0;
boolean title = false;
if(str.substring(0,1).equals("`")) {
str = str.substring(1);
title = true;
}
int len = str.length();
for(int i=0;iString s = String.valueOf(str.charAt(i));
pos=i;
bracket = 0;
if(!lc.contains(s)){//如果没遇到运算符
if("(".equals(s)) {//如果遇到左括号
if(funMap.containsKey(bds)){//如果左括号前是函数
for (int j = i+1; j < len; j++) {//从左括号后开始循环
pos++;//累计移动字符位数
String ts = String.valueOf(str.charAt(j));//单个字符
//       reval+=ts;
if("(".equals(ts))//如果是左括号累计
bracket++;
else if(")".equals(ts)){//如果是右括号进行减少
bracket--;
if(bracket==-1){//如果是-1,标识括号结束
reval=reval.substring(0,reval.length()-bds.length());//重新获得去掉函数头的表达式
reval+=funCalculate(str.substring(i+1,j), bds);//表达式加上函数结果,形成新表达式
i=pos;//计数器增加
bds="";//函数头清空
break;//退出本次循环
}
}
}
}else{//如果是普通运算
for (int j = i+1; j < len; j++) {
pos++;
String ts = String.valueOf(str.charAt(j));
if("(".equals(ts))
bracket++;
else if(")".equals(ts)){
bracket--;
if(bracket==-1){
reval+=calculate(str.substring(i+1,pos));
i=pos;
bds="";
break;
}
}
}
}
}else{//累加总表达式和最后一个运算数(或函数)
bds+=s;
reval+=s;
}
}else{//遇到运算符最后一个运算数(或函数)清空
bds="";
reval+=s;
}
}
if(title)reval = "-"+reval;
return szys(reval);
}
/**
* 函数运算
* @param gs
* @param flag
* @return
*/
public static String funCalculate(String gs,String funStr) {
String rval = "0";
if(funMap.containsKey(funStr)) {
int[] csi = funMap.get(funStr);
try{
if(csi[0]==0) {//java内部函数,通过反射调用
Class[] cs = new Class[csi[1]];
Object[] objs = new Object[csi[1]];
String[] gss = zlcs(gs);
for (int i = 0; i < csi[1]; i++) {
cs[i] = double.class;
objs[i] = new Double(calculate(gss[i]));
}
Class cls = Class.forName("java.lang.Math");
Method m = cls.getMethod("abs", cs);
rval = String.valueOf(m.invoke(cls, objs));
}else if(csi[0]==1) {//自定义函数
rval = customFun(gs, funStr);
}
}catch (Exception e) {
}
}
return rval;
}
//公式里的参数分割
public static String[] zlcs(String str) {
int len = str.length();
boolean flag = true;
String tstr = "";
for (int i = 0; i < len; i++) {
String s = String.valueOf(str.charAt(i));
if("(".equals(s)) {
flag = false;
}else if(")".equals(s)) {
flag = true;
}
if(flag && ",".equals(s)) {
tstr+="@";
}else{
tstr+=s;
}
}
return tstr.split("@");
}
/**
* 四则运算表达式处理
* @param str
* @return
*/
public static String szys(String gs) {
gs = gs+"+0"; //因为下面的计算是遇到符号才进行,所以多加入一个计算符号,不影响值.
String c1 = "";//第一个运算符号
String c2 = "";//第二个运算符号
String s1 = "";//第一个运算数
String s2 = "";//第二个运算数
String s3 = "";//第三个运算数
int len = gs.length();
for (int i = 0; i < len; i++) {
String s = String.valueOf(gs.charAt(i));//获得该位置字符并转换成字符串做比较
if(lc.contains(s)) { //如果是运算符号
if(c1.length()==0)//如果第一个运算符号为空,加入
c1 = s;
else if(c2.length()==0){//否则,如果第二个运算符号为空,加入
c2 = s;//第二个运算符号
if("+".equals(c2) || "`".equals(c2)){//如果第二个运算符号级别低,那么进行计算
s1 = _4zys(s1, c1, s2);//第一个和第二个数计算
c1 = c2;//保存第二个运算符,其他为空
c2 = "";
s2 = "";
}
}else{//上述都保存过
if("+".equals(s) || "`".equals(s)){//如果第三个运算符级别低,进行运算
s2 = _4zys(s2, c2, s3);//先算第二三个数,保存至第二个
s1 = _4zys(s1, c1, s2);//再算第一二个,保存至第一个
c1 = s;//保存当前运算符,其他为空
s2 = "";
c2 = "";
s3 = "";
}else{//如果第三个运算符级别高
s2 = _4zys(s2, c2, s3);//先算第二三个数,保存至第二个
c2 = s;//前面不动,保存运算符
s3 = "";
}
}
}else if(s1.length()>0 && c1.length()>0 && c2.length()==0) {//如果第一个数,第一个运算符已保存,第二个运算符未保存,保存第二哥数
s2+=s;
}else if(c1.length()==0){//如果没有运算符,保存第一个数
s1+=s;
}else if(s1.length()>0 && s2.length()>0 && c1.length()>0 && c2.length()>0) {//如果第一二个数和运算符都有,保存第三个数
s3+=s;
}
}
return s1;
}
/**
* 基本四则运算
* @param c1 运算数1
* @param s1  运算符(加减乘除)
* @param c2 运算数2
* @return
*/
public static String _4zys(String c1,String s1,String c2) {
String reval = "0";
try{
double ln = Double.valueOf(c1).doubleValue();
double rn = Double.valueOf(c2).doubleValue();
if("+".equals(s1)) {
return (ln+rn)+"";
}else if("`".equals(s1)){
return (ln-rn)+"";
}else if("*".equals(s1)){
return (ln*rn)+"";
}else if("/".equals(s1)){
if(rn==0)
return reval;
else
return (ln/rn)+"";
}
}catch(Exception e){
}finally {}
return reval;
}
/**
* @param args
*/
public static void main(String[] args) {
String gs = "if(4 > 3,if( ( 2 - 1 ) /  ( 0.0001 ) * 3 > 3  , ( 2 - ( 2 - 1 ) /  ( 0.0001 ) * 3  ) * 0.8 ,0),  ( 2 + ( 3 - 2 ) /  ( 0.0001 ) *1  )  * 1)";
//  进行四则运算获得结果
System.out.println(szys(strCast("3-4*-5+5")));
//  函数运算结果
System.out.println(calculate(strCast("3+abs(mod(4,if(2>3,1,3))-abs(2*4))*5+5")));
System.out.println(calculate(strCast("if(0.0*2>=10.0,0,10.0-0.0*2)")));
System.out.println(calculate(strCast("if(0<2,(10.0-0*5)*0.8,0)")));
System.out.println(calculate(strCast(gs)));
}
}

可能还有不完善的地方,希望大家多提宝贵意见!