用java创建一个表达式计算器和脚本解释器

本文介绍了如何使用Java创建一个表达式计算器和脚本解释器,通过自定义公式进行计算,例如根据变量计算表达式。示例中展示了如何设置变量并进行复杂的表达式计算,包括字符串操作和条件判断。该类还可以扩展为一个简单的脚本语言解释器,处理自定义的逻辑和变量操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个简单的表达式计算,有时候我们要在程序中对某些自定义的公式进行计算。

如定制化的一些条件,如根据某个变量来决定界面元素的颜色

我们只要对这个类稍微扩展即可,例如我们重载getObjValue方法,

然后定义一个变量池,就可以实现对诸如 calculateExp("50-Qty*((1+2)*3)+2")的计算。

getObjValue()中实现对于Qty可以从变量池获得数据。

更多的扩展可以参照后面的类,可以做一个自己的脚本语言解释器。

        Polynomial dt =new Polynomial();
            long begin =System.currentTimeMillis();
            VariableFactory vf = new VariableFactory();
            vf.setVariable("A","Select * from mis_rwe where a=");
            vf.setVariable("B","150");
            vf.setVariable("conf ","'5'");
            dt.setDataFactory(vf);
            dt.calcuPolyn("set A=IIF(obj(b)=150:add(obj(a)+obj(conf),str(\" order by desc\")),:空)");//strExp
            dt.calcuPolyn("set A=str('新的变量值:')+obj(a)");//strExp
            System.out.println(vf.getVariable("a"));
            dt.calcuPolyn("set B=100");//strExp
            dt.calcuPolyn("set A=IIF(obj(b)=100:str('(变更B变量后)')+obj(a),:空)");//strExp
            System.out.println(vf.getVariable("a"));
            dt.calcuPolyn("set A=replace(Obj(A),变更B变量后,str('替换函数操作后'))");//strExp
            System.out.println(vf.getVariable("a"));
            dt.calcuPolyn("set A=replace(\"测试 test\" + ' W J G ', test, newstr)");//strExp
            System.out.println(vf.getVariable("a"));
            for(int i=0; i<10;i++)
                dt.calcuPolyn("set B=obj(b)+'100'");
            System.out.println("B="+vf.getVariable("b"));
            System.out.println("运行时间:"+(System.currentTimeMillis()-begin) +"毫秒");

 

/*--------------------------------------------------
1.实现表达式的计算;
2.实现简单的加、减、乘、除、括号运算。
3.例:calculateExp("50-10*((1+2)*3)+2")=-38
----------------------------------------------------*/

import java.util.Vector;
import java.util.Hashtable;
import java.util.Stack;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import com.jgwang.IDataFactory;

public class CalculatorA
{
    protected IDataFactory varFactory;  //当前语句的变量库
    protected Hashtable localVarFact;

    protected static Vector funct;
    protected static Hashtable pri;
    protected static String NOSOFunction="No so Function";

    public static FastHashMap buildedStates;

    static 
    {
        funct=new Vector();
        funct.addElement("+");
        funct.addElement("-");
        funct.addElement("*");
        funct.addElement("/");
        funct.addElement("(");
        funct.addElement(")");
        pri=new Hashtable();
        pri.put("+","1");
        pri.put("-","1");
        pri.put("*","2");
        pri.put("/","2");
        pri.put("(","10");
        pri.put(")","0");
        buildedStates = new FastHashMap();
    }

    public CalculatorA()
    {
        varFactory = new VariableFactory();
    }

    public void setDataFactory(IDataFactory v)
    {
        this.varFactory = v;
    }

    public void setVariable(String param, String v)
    {
        if(this.varFactory==null)
            varFactory = new VariableFactory();
        varFactory.setVariable(param, v);
    }

/*------------------------分析表达式---------------------------*/
    public Vector analyseExp(String strExp)  
    {
        boolean isStrBegin = false;
        try
        {
            Vector strObjs = new Vector();
            Vector obj = new Vector();
            byte[] bExps = strExp.getBytes();
            byte[] bExps1={'+'};
            char qmark='\'';
            if (strExp == null) 
                return null;
            int isFunct = 0;
            for(int i=0; i < bExps.length; i++)
            {
                int cPr=0;
                bExps1[0]=bExps[i];
                if((char)bExps1[0]=='"' || (char)bExps1[0]=='\'')
                {
                    if(!isStrBegin) qmark = (char)bExps1[0];
                    obj.addElement(new Byte(bExps1[0]));
                    if(qmark == (char)bExps1[0])
                        isStrBegin = !isStrBegin;
                    continue;
                }
                else if(isStrBegin)
                {
                    obj.addElement(new Byte(bExps1[0]));
                    continue;
                }            
                if((char)bExps1[0]==' ') continue;
                if (funct.indexOf(new String(bExps1))>=0)
                {

                    if('('==(char)bExps1[0] && obj.size()>0)
                    {
                        obj.addElement(new Byte(bExps1[0]));
                        isFunct ++;
                        continue;
                    }
                    else if(')'==(char)bExps1[0] && isFunct>0) 
                    {
                        obj.addElement(new Byte(bExps1[0]));
                        isFunct --;
                        continue;
                    }

                    if(isFunct==0)
                    {
                        if(obj.size()>0)
                        {
                            byte[] strObjBA= new byte[obj.size()];
                            for(int k=0; k<strObjBA.length ;k++)
                                strObjBA[k]=((Byte)obj.elementAt(k)).byteValue();
                            strObjs.addElement( new String(strObjBA));
                        }
                        if(obj.size()==0    && '-'==(char)bExps1[0])
                              strObjs.addElement("0");
                        strObjs.addElement(new String(bExps1));
                        obj.clear();
                    }
                    else
                        obj.addElement(new Byte(bExps1[0]));
                }
                else 
                {
                    obj.addElement(new Byte(bExps1[0]));
                }
            }
            if(obj.size()>0)
            {
                byte[] strObjBA= new byte[obj.size()];
                for(int k=0; k<strObjBA.length ;k++)
                    strObjBA[k]=((Byte)obj.elementAt(k)).byteValue();
                strObjs.addElement( new String(strObjBA));
            }
            return strObjs;
        }
        catch(Exception e)
        {
            return null;
        }
    }

/*------------------------计算表达式的值---------------------------*/
    public String calculateExp(String strExp)    throws Exception
    {
        /*Vector strObjs = (Vector)buildedStates.get(strExp);
        System.out.println(strObjs!=null?strObjs.toString():"");
        if(strObjs==null)
        {
            strObjs = analyseExp(strExp);
            //if(strObjs.size()>0)
                buildedStates.put(strExp,analyseExp(strExp));
        }
        else if(strObjs.size()==1)
            return getObjValue((String)strObjs.elementAt(0));*/
        Vector strObjs = analyseExp(strExp);
        Stack  cacuObj = new Stack();
        Stack  cacuFunc = new Stack();
        String strObj = "";
        String value="";
        int pr=0;
        if(strObjs.size()==1)
        {
            strObj = (String)strObjs.elementAt(0);
            if(strObj.startsWith("\"") || strObj.startsWith("'"))
                strObj = getString(strObj);
            return caculateValue(strObj,null,null);
        }
        for(int i=0; i<strObjs.size() ;i++)
        {
            strObj=(String)strObjs.elementAt(i);
            if(strObj.startsWith("\"") || strObj.startsWith("'"))
                strObj = getString(strObj);

            if(funct.indexOf(strObj)>=0)
            {
                int cPr=Integer.parseInt((String)pri.get(strObj));
                if(cPr>pr) {
                    cacuFunc.push(strObj);
                    if(cPr==10) pr=-1;  else pr=cPr;
                    continue;
                }
                if(strObj.equals(")"))
                {
                    if(pr==-1) cacuFunc.pop();
                    String f=(String)cacuFunc.pop();
                    while(!f.equals("(")) 
                    {
                        value=caculateValue((String)cacuObj.pop(),(String)cacuObj.pop(),f);
                        cacuObj.push(value);
                        f=(String)cacuFunc.pop();
                    }
                    if(cacuFunc.size()>0)
                        pr=Integer.parseInt((String)pri.get((String)cacuFunc.elementAt(cacuFunc.size()-1)));
                    else
                        pr=-1;
                    if(pr==10) pr=-1;
                }
                else 
                {
                    while(cPr<=pr) 
                    {
                        if(cacuFunc.size()>0 && cacuObj.size()>1)
                        {
                            value=caculateValue((String)cacuObj.pop(),(String)cacuObj.pop(),(String)cacuFunc.pop());
                            cacuObj.push(value);
                            if(cacuFunc.size()>0)
                                pr=Integer.parseInt((String)pri.get((String)cacuFunc.elementAt(cacuFunc.size()-1)));
                            else
                                pr=-1;
                        }
                        else
                            pr=-1;
                        if(pr==10) pr=-1;
                    }                        
                    cacuFunc.push(strObj);
                    pr=cPr;
                }
            }
            else
            {
                cacuObj.push(strObj);
            }    
            
            if(i==strObjs.size()-1)
            {
                while(cacuFunc.size()>0 && cacuObj.size()>1) 
                {
                    value=caculateValue((String)cacuObj.pop(),(String)cacuObj.pop(),(String)cacuFunc.pop());
                    cacuObj.push(value);
                }            
            }
        }
        return value;
    }

/*------------------------计算操作符---------------------------*/
    public String caculateValue(String strObj1,String strObj2,String cacuFunc)  throws Exception
    {
        try
        {

            if(strObj1.indexOf("(")>0)
                strObj1 = calcuFunction(strObj1);
            strObj1 = getObjValue(strObj1);
            if((strObj2==null)||(cacuFunc==null))
                    return strObj1;
            if(strObj2.indexOf("(")>0)
                strObj2 = calcuFunction(strObj2);
            strObj2 = getObjValue(strObj2);
                
            return cacuValue(strObj1,strObj2,cacuFunc);
        }
        catch(Exception e)
        {
            throw e;
        }
    }

    public String cacuValue(String strObj1,String strObj2,String cacuFunc)  throws Exception
    {
        double value=0;
        try
        {
            //System.out.println(strObj2+cacuFunc+strObj1);
            if(cacuFunc.equals("+") &&(!isNumber(strObj2) || !isNumber(strObj1)))
                    return strObj2+ strObj1;
            if(strObj1.length()==0)
                strObj1 = "0";
            if(strObj2.length()==0)
                strObj2 = "0";
            if(cacuFunc.equals("+") )
                value=Double.valueOf(strObj2).doubleValue()+Double.valueOf(strObj1).doubleValue();
            else if(cacuFunc.equals("-")) 
                value=Double.valueOf(strObj2).doubleValue()-Double.valueOf(strObj1).doubleValue();
            else if(cacuFunc.equals("*")) 
                value=Double.valueOf(strObj2).doubleValue()*Double.valueOf(strObj1).doubleValue();
            else if(cacuFunc.equals("/")) 
            {
                if(Double.valueOf(strObj1).doubleValue()!=0)
                    value=Double.valueOf(strObj2).doubleValue()/Double.valueOf(strObj1).doubleValue();
                else value=0;
            }
            return String.valueOf(value);
        }
        catch(Exception e)
        {
            //System.out.print(e);
            throw e;
        }
    }

    public static boolean isNumber(String arg) 
    {
         Pattern p=null; //正则表达式
         Matcher m=null; //操作的字符串
         p = Pattern.compile("\\-?\\d*\\.?\\d*[Ee]?\\d{0,3}");
         m = p.matcher(arg);
         return m.matches();
    }
    
    protected String getObjValue(String obj)
    {
        return obj;
    }
/*------------------------计算函数---------------------------*/
    public String calcuFunction(String functStatement) throws Exception
    {
        if(functStatement.toLowerCase().startsWith("str("))
        {
            String rv =  functStatement.substring(4,functStatement.lastIndexOf(")"));
            return rv.replaceFirst("['\"]","").replaceAll("['\"]$","");
        }
        String functName = functStatement.substring(0,functStatement.indexOf("("));
        String statement = functStatement.substring(functStatement.indexOf("(")+1,functStatement.length()-1);
        String[] args = split(functName,statement, ',');
        for (int i=0; i<args.length; i++)
        {
            args[i] = calculateExp(args[i]);
        }
        String v = calcuFunctValue(functName, args);
        return v;
    }

    protected String[] split(String functName, String v, char splitChar)
    {
        if(functName.equalsIgnoreCase("str"))
            return new String[]{v};
        StringBuffer objStr = new StringBuffer("");
        int isFunct = 0;
        for(int i=0; i < v.length(); i++)
        {
            if(v.charAt(i)=='(')
                isFunct ++;
            if(v.charAt(i)==')')
                isFunct --;
            if(v.charAt(i)==splitChar && isFunct==0)
                objStr.append("&"+splitChar+"&");
            else
                objStr.append(v.charAt(i));
        }    
        return new String(objStr).split("&"+splitChar+"&");
    }
    
    public String calcuFunctValue(String functName, String[] args) throws Exception
    {
        //functName = functName.toUpperCase();
        if(functName.equalsIgnoreCase("str"))
        {
            return args[0];
        }
        else if(functName.equalsIgnoreCase("obj"))
        {
            return  varFactory.getVariable(args[0]);
        }
        return extFunct(functName,args);
    }

    protected String extFunct(String functName, String[] args) throws Exception
    {
        throw new Exception("No so Function! " + functName);
    }

    public static String getString(String str)
    {
        return  str.replaceFirst("['\"]","").replaceAll("['\"]$","");
    }

    public static void main(String argc[])
    {
        try{
            CalculatorA dt =new CalculatorA();
            String strExp=argc[0];//"(25+(10*10)-100)+(5-4)";
            System.out.println(strExp+"="+dt.calculateExp(strExp));
        }
        catch(Exception e)
        {
            e.printStackTrace(System.out);
        }
    }
}
 

提供一个参考的方法,虽然原始,可以做一个自己的脚本语言解释器。

=========================================
//import java.util.*;
import com.jgwang.ITable;
import javax.servlet.http.HttpServletRequest;
import com.jgwang.ISysParamPool;
import com.jgwang.sys.Sys;
import com.jgwang.util.SysDate;
import com.jgwang.IPolynomial;

public class Polynomial  extends CalculatorA implements IPolynomial
{
    protected ITable table;
    protected ISysParamPool sys;
    protected HttpServletRequest request;

    public Polynomial()
    {
        super();
    }
    
    public void setTable(ITable table)
    {
        this.table = table;
    }

    public void setSys(ISysParamPool sys)
    {
        this.sys = sys;
    }

    public void setRequest(HttpServletRequest request)
    {
        this.request = request;
    }

    public String transStateValueExt(String state) throws Exception
    {
        return transStateValue( state);
    }
    public String transStateValue(String state) throws Exception
    {
        if(state==null || state.length()==0)
            return "";
        //公式计算项目
        while(state.indexOf("${")>=0 && state.indexOf("}")>=0)
        {
            String formula = "";
            formula = state.substring(state.indexOf("${")+2,state.indexOf("}"));
            String rv = calcuPolyn(formula);
            state = state.substring(0,state.indexOf("${")) + rv 
                + state.substring(state.indexOf("}")+1);
        }
        return state;
    }

    /*     sample: IIF(FV(Status)=1:red , : )   IIF(bool:value,bool:value,:defaultValue)
        字符串的几种表示方法 "string", 'string', str('string'), str("string"), str(无空格字符串),直接书写的无空格字符串
        对于没有引号的字符串,系统会自动将空格去掉。对于长字符串,最好采用变量,然后在多项式中用obj(var)引用。
        判断语句等于采用“=”号,对于赋值语句采用SQL语言格式的 set var=value;方式(LISP语言采用setq var=value;)。
        对于对象操作,一律必须使用obj(object id)方式定义。
    */
    public String calcuPolyn(String state) throws Exception
    {
        if(state.startsWith("set "))
        {
            String var = state.substring(4,state.indexOf("="));
            String value = state.substring(state.indexOf("=")+1);
            value =calcuPolyn(value);
            varFactory.setVariable(var, value);
            return value;
        }
        else if(state.startsWith("IIF"))
        {
            state = state.substring(4,state.lastIndexOf(")"));
            String[] args = split("IIF",state,',');
            for(int i=0; i<args.length; i++)
            {
                String[] st = split("IIF",args[i],':');
                if(stateAnalye(st[0]))
                    return calculateExp(st[1]);
            }
            return "";
        }
        return calculateExp(state);
    }

    protected String extFunct(String functName, String[] args) throws Exception
    {
        if(functName.equalsIgnoreCase("FV"))
        {
            if(table==null)
                return args[0];
            return table.getValue(args[0]);
        }
        else if(functName.equalsIgnoreCase("Rqstobj"))
        {
            String v = request.getParameter(args[0]);
            return v==null?"":Sys.toLocalStr(v);
        }
        else if(functName.equalsIgnoreCase("sysobj"))
        {
            String v = sys.getParam(args[0]);
            return v==null?"":v;
        }
        else if(functName.equalsIgnoreCase("systime"))
        {
            return SysDate.getToday(args[0]);
        }
        else if(functName.equalsIgnoreCase("ord"))
        {
            String seq = args[0];
            String fmt = args[1];
            if(fmt.length()<seq.length())
                return seq;
            if(fmt.endsWith("d"))
                return fmt.substring(0,fmt.length() - seq.length()) + seq;
            else
                return seq + fmt.substring(seq.length());
        }
        else if(functName.equalsIgnoreCase("replace"))
        {
            return args[0].replaceAll(args[1],args[2]);
        }
        else if(functName.equalsIgnoreCase("ADD"))
        {
            if(args.length<2)
                return args[0];
            return args[0]+args[1];
        }
        else if(functName.equalsIgnoreCase("MAX"))
        {
            double value = Double.valueOf(args[0] ).doubleValue();
            for (int i=1; i<args.length; i++)
            {
                if(value<Double.valueOf(args[i] ).doubleValue()-0.0001)
                    value = Double.valueOf(args[i] ).doubleValue();
            }
            return  String.valueOf(value);
        }
        else if(functName.equalsIgnoreCase("SMAX"))
        {
            String arg = args[0];
            for (int i=1; i<args.length; i++)
            {
                if(args[i].compareTo(arg)>0)
                    arg = args[i];
            }
            return  arg;
        }
        else if(functName.equalsIgnoreCase("Decimal"))
        {
            return args[0];
        }
        return "ERROR:"+functName;
    }

    protected boolean stateAnalye(String state)  throws Exception
    {
        if(state.length()==0)
            return true;
        String funct = "=";
        String[] states ;
        if(state.indexOf(">=")>=0)
        {
            states = state.split(">=");
            funct = ">=";
        }
        else if(state.indexOf("!=")>=0)
        {
            states = state.split("!=");
            funct = "!=";
        }
        else if(state.indexOf("<=")>=0)
        {
            states = state.split("<=");
            funct = "<=";
        }
        else
        {
            states = state.split("[>=<]");
            if(state.indexOf(">")>=0) funct = ">";
            if(state.indexOf("<")>=0) funct = "<";
        }
        if(states.length<2)
            return false;
        return compareState(states[0], states[1], funct);
    }

    protected boolean compareState(String obj1, String obj2, String funct)  throws Exception
    {
        obj1 = calculateExp(obj1);
        obj2 = calculateExp(obj2);
        if(!isNumber(obj1) || !isNumber(obj2))
        {
            int rv = obj1.compareTo(obj2);
            if(funct.equals("!=")) return rv!=0;
            if(rv==0) return funct.indexOf("=")>=0;
            if(rv<0) return funct.indexOf("<")>=0;
            if(rv>0) return funct.indexOf(">")>=0;
            return false;
        }
        else
        {
            if(obj1.length()==0) obj1 = "0";
            if(obj2.length()==0) obj2 = "0";
            double value1=Double.valueOf(obj1).doubleValue();
            double value2=Double.valueOf(obj2).doubleValue();
            if(funct.equals("=")) return Math.abs(value1-value2) < 0.001;
            if(funct.equals(">=")) return value1-value2 >= -0.001;
            if(funct.equals("<=")) return value1-value2 <= 0.001;
            if(funct.equals(">")) return value1-value2 > 0.001;
            if(funct.equals("<")) return value1-value2 < -0.001;
            return false;
        }
    }

    protected String getObjValue(String obj)
    {
        obj = super.getObjValue(obj);
        return obj;
    }

    public static void main(String argc[])
    {
        try{
            Polynomial dt =new Polynomial();
            long begin =System.currentTimeMillis();
            VariableFactory vf = new VariableFactory();
            vf.setVariable("A","Select * from mis_rwe where a=");
            vf.setVariable("B","150");
            vf.setVariable("conf ","'5'");
            dt.setDataFactory(vf);
            dt.calcuPolyn("set A=IIF(obj(b)=150:add(obj(a)+obj(conf),str(\" order by desc\")),:空)");//strExp
            dt.calcuPolyn("set A=str('新的变量值:')+obj(a)");//strExp
            System.out.println(vf.getVariable("a"));
            dt.calcuPolyn("set B=100");//strExp
            dt.calcuPolyn("set A=IIF(obj(b)=100:str('(变更B变量后)')+obj(a),:空)");//strExp
            System.out.println(vf.getVariable("a"));
            dt.calcuPolyn("set A=replace(Obj(A),变更B变量后,str('替换函数操作后'))");//strExp
            System.out.println(vf.getVariable("a"));
            dt.calcuPolyn("set A=replace(\"测试 test\" + ' W J G ', test, newstr)");//strExp
            System.out.println(vf.getVariable("a"));
            for(int i=0; i<10;i++)
                dt.calcuPolyn("set B=obj(b)+'100'");
            System.out.println("B="+vf.getVariable("b"));
            System.out.println("运行时间:"+(System.currentTimeMillis()-begin) +"毫秒");

        }
        catch(Exception e)
        {
            e.printStackTrace(System.out);
        }
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值