日期:2014-05-20  浏览次数:20754 次

字符串如何转化成运算式??????????
如String s="60*10"
怎么把这个字符串运算出来???

------解决方案--------------------
这是前段时间写的一个表达式计算的方法
Java code

package com.hd.fa.util.depreciation;

import java.util.HashMap;

import com.hd.util.bean.DynaBean;

/**
 * 把正常的表达式转换成逆波兰式
 * 并工具系统的特点,计算折旧类型对应的折旧额
 *
 */
public class Depr {

    /**
     * 原表达式
     */
    private String exp;
    /**
     * 用来存放一个原表达式中的一个一个的值
     */
    private String token;

    /**
     * 零时变量存放表达式中光标的位置
     */
    private int expIdx;

    /**
     * 转换成逆波兰式后的字符串
     */
    private String expR;

    /**
     * 把逆波兰式的字符串顺序压栈的栈的对象
     */
    private Stack expStack;

    /**
     * 设备的信息的bean;
     */
    private DynaBean bean; 

    /**
     * 折旧表达式对应的逆波兰式
     */
    private static HashMap regularMap;

    /**
     * error 编码
    */
    private static final int SYNERR = 0;

    /**
     * 没有结束
     */
    private static final int UNBPAREN = 1;

    /**
     * 其他
     */
    private static final int NOEXP = 2;

    /**
     * 表达式的结束符
     */
    private static final String EOE = "\0";

    /**
     * 表达式中的分隔符
     */
    private static final String SEPERATOR = ",";


    /**
         * 处理错误信息
         * 
         * @param err 错误编码
         * @throws RpnException  错误的类
         */
    public void handleErr(int err) throws RpnException {
        String[] errs = new String[]{"SYNTAX ERROR", "UNBALANCE PARENTHESE", "NO EXPRESSSION" };
        throw new RpnException(errs[err]);
    }

    /**
     * 判断字串是否是一个运算符号
     * @param a 需要判断的字符
     * @return boolean 如果是则返回true
     */
    private boolean isDelim(char a) {
        if (" +-*%/()".indexOf(a) != -1) {
            return true;
        }
        return false;
    }

    /**
     * 得到原表达式中的下一个元素
     */
    private void getToken() {
        token = "";

        if (expIdx == exp.length()) {
            token = EOE;
            return;
        }

        // If there is white space in expression
        while (expIdx < exp.length()
                && Character.isWhitespace(exp.charAt(expIdx))) {
            ++expIdx;
        }
        if (expIdx == exp.length()) {
            token = EOE;
            return;
        }

        if (Character.isDigit(exp.charAt(expIdx))) {
            while (expIdx < exp.length()
                    && Character.isDigit(exp.charAt(expIdx))) {
                token = token + exp.charAt(expIdx);
                expIdx++;
            }
        } else if (isDelim(exp.charAt(expIdx))) {
            token = token + exp.charAt(expIdx);
            expIdx++;
        } else if (Character.isLetterOrDigit(exp.charAt(expIdx))) {
            while (expIdx < exp.length()
                    && Character.isLetter(exp.charAt(expIdx))) {
                token = token + exp.charAt(expIdx);
                expIdx++;
            }
        }
    }

    /**
     * 程序的入口,根据表达式和传过来的bean来计算折旧的值
     * @param assetBean 需要折旧的资产的记录
     * @return double  该资产当月的折旧费用
     * @throws RpnException 异常
     */
    public double getResult(DynaBean assetBean) throws RpnException {
        exp = getRegularOfDep(assetBean.getStr("DEPRTYPE"));
        this.bean = assetBean;
        if (regularMap == null) {
            regularMap = new HashMap();
        }
        if (regularMap.containsKey(exp)) {
            expR = (String) regularMap.get(exp);
        } else {
            expIdx = 0;
            getToken();
            if (token.length() == 0) {
                handleErr(NOEXP);
            }

            expR = convert();

            if (!token.equals(EOE)) {
                handleErr(SYNERR);
            }
            regularMap.put(exp, this.expR);
        }
        this.putStringIntoStack();
        return this.calculate();
    }

    /**
     * 得到各种折旧类型对应的折旧公式
     * @param type
     *                 设备的折旧类型
     * @return boolean
     *            如果审核成功则返回true,否则返回false
     */
    private String getRegularOfDep(String type) {
            return "(FORMERCOST-DEPRTOTAL-FINALCOST-TOTALREDUCE+RETURNREDUCE)/(ASLIFE*12-DEPREDMONTH)"
                .replaceAll("ASLIFE", "(ASLIFE/12)");
    }
    
    /**
     * 处理 '+' 和 '-' 的操作
     * @return String  返回处理后的表达式
     * @throws RpnException 异常
     */
    private String convert() throws RpnException {
        String result = "";
        char op;

        result = convert2();

        while ((op = token.charAt(0)) == '+' || op == '-') {
            getToken();
            String partialResult = convert2();
            result = result + SEPERATOR + partialResult + SEPERATOR + op;
        }
        return result;
    }

    /**
     * 处理 '*' 和 '/'  和 '%' 的操作
     * @return String  返回处理后的表达式
     * @throws RpnException 异常
     */
    private String convert2() throws RpnException {
        String result = "";
        char op;

        result = convert3();

        while ((op = token.charAt(0)) == '*' || op == '/' || op == '%') {
            getToken();
            String partialResult = convert3();
            result = result + SEPERATOR + partialResult + SEPERATOR + op;
        }
        return result;
    }

    /**
     * 处理 () 的操作
     * @return String  返回处理后的表达式
     * @throws RpnException 异常
     */
    private String convert3() throws RpnException {
        String result = "";

        if (token.charAt(0) == '(') {
            getToken();
            result = convert();
            if (token.charAt(0) != ')') {
                handleErr(UNBPAREN);
            }
        } else {
            result = token;
        }
        getToken();
        return result;
    }

    /**
     * 把生产的逆波兰式字串放入到栈中,便于计算
     */
    private void putStringIntoStack() {
        String[] list = this.expR.split(",");
        expStack = new Stack();
        for (int i = 0; i < list.length; i++) {
            if (!list[i].equals("")) {
                expStack.push(list[i]);
            }
        }
    }


    /**
     * 根据表达式计算折旧费用
     * @return double 折旧费用
     */
    private double calculate() {
        String temp = (String) expStack.pop();
        if (temp.equals("+")) {
            double temp1 = calculate();
            double temp2 = calculate();
            return temp2 + temp1;
            
        } else if (temp.equals("-")) {
            double temp1 = calculate();
            double temp2 = calculate();
            return temp2 - temp1;
        } else if (temp.equals("*")) {
            double temp1 = calculate();
            double temp2 = calculate();
            return temp2 * temp1;
        } else if (temp.equals("/")) {
            double temp1 = calculate();
            double temp2 = calculate();
            return temp2 / temp1;
        } else {
            //这里你只是用到了数字,没有用到表达式 就直接返回数字
            if (isNumber(temp)) {
                return Double.parseDouble(temp);
            } else {
                 
                return bean.getDouble(temp);
            }
        }
    }
    
    /**
     * 判断一个字串是否是一个数字
     * @param str 需要判断的字串
     * @return boolean 如果是数字类型则返回true
     */
    private boolean isNumber(String str) {
        return str.matches("[+-]?[\\d]+[.]?[\\d]+");
    }
}