日期:2014-05-20 浏览次数:20823 次
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]+"); } }