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