package study.java.hanyx.rpn.crmPatternExp;
import java.util.ArrayList;
import java.util.List;
/**
*
* Copyright: Asiainfo-Linkage
*
* @desc: 采用逆波兰表达式进行算术运算
* @version: v1.0
* @author: lvyh
* @date: 2011.02.20
*/
public class Arithmetic {
private final static String OP1 = "+";
/**
* -
*/
private final static String OP2 = "-";
/**
* *
*/
private final static String OP3 = "*";
/**
* /
*/
private final static String OP4 = "/";
/**
* (
*/
private final static String OPSTART = "(";
/**
* )
*/
private final static String OPEND = ")";
public Arithmetic(String exp) {
}
/**
* 分析四则运算表达式,将数字与运算符进行分解
*/
public static List parse(String exp) {
// 四则运算解析
List expList = new ArrayList();
int length = exp.length();
String tempStr = "";
for (int i = 0; i < length; i++) {
String tempChar = exp.substring(i, i + 1);
if (isNumber(tempChar)) {
tempStr += tempChar;
} else {
if (!tempStr.equals("")) {
expList.add(tempStr);
}
expList.add(tempChar);
tempStr = "";
}
}
if (!tempStr.equals("")) {
expList.add(tempStr);
}
return expList;
}
/**
* 判断当前字符或字符串是否是数字
*
* @param str
* @return
*/
public static boolean isNumber(String str) {
return str.startsWith("0") || str.startsWith("1") || str.startsWith("2") || str.startsWith("3") || str.startsWith("4") || str.startsWith("5") || str.startsWith("6") || str.startsWith("7") || str.startsWith("8") || str.startsWith("9") || str.startsWith(".");
}
/**
* 判断当前字符是否是 (
*
* @param str
* @return
*/
public static boolean isParenthesesStart(String str) {
return str.equals(OPSTART);
}
/**
* 判断当前字符是否是 )
*
* @param str
* @return
*/
public static boolean isParenthesesEnd(String str) {
return str.equals(OPEND);
}
/**
* 判断当前字符是否是高优先级运算符 * /
*
* @param str
* @return
*/
public static boolean isHeighOperator(String str) {
if (str.equals(OP3) || str.equals(OP4)) {
return true;
} else {
return false;
}
}
/**
* 对比两个字符串的优先级
*
* @param str1
* @param str2
* @return
*/
public static boolean compare(String str1, String str2) {
if (str1.equals(OPSTART)) {
return false;
}
if (isHeighOperator(str2)) {
return false;
} else {
if (isHeighOperator(str1)) {
return true;
} else {
return false;
}
}
}
/**
* 将分解后的四则运算列表构建成逆波兰表达式列表
*/
public static List createRPN(String exp) {
List expList = Arithmetic.parse(exp);
// 存放逆波兰表达式
List rpnList = new ArrayList();
Stack stack = new Stack();
int length = expList.size();
for (int i = 0; i < length; i++) {
String c = (String) expList.get(i);
// 如果是数字,直接放到逆波兰链表的最后
if (isNumber(c)) {
rpnList.add(c);
} else {
// 如果不是数字
// 如果是左括号,则直接将左括号压入栈
if (isParenthesesStart(c)) {
stack.push(c);
} else if (isParenthesesEnd(c)) {
// 如果是右括号
// 进行出栈操作,直到栈为空或者遇到第一个左括号
while (!stack.isEmpty()) {
// 将栈顶字符串做出栈操作
String tempC = stack.pop();
if (!tempC.equals(OPSTART)) {
// 如果不是左括号,则将字符串直接放到逆波兰链表的最后
rpnList.add(tempC);
} else {
// 如果是左括号,退出循环操作
break;
}
}
} else {
// 如果栈内为空
if (stack.isEmpty()) {
// 将当前字符串直接压栈
stack.push(c);
} else {
// 如果栈不为空
// 比较栈顶字符串与当前字符串的优先级,
if (compare(stack.top(), c)) {
// 如果栈顶元素的优先级大于当前字符串,则进行出栈操作
// 将栈顶元素直接放到逆波兰链表的最后
// 直到栈内为空,或者当前元素的优先级不小于栈顶元素优先级
while (!stack.isEmpty() && compare(stack.top(), c)) {
rpnList.add(stack.pop());
}
}
// 将当前字符串直接压栈
stack.push(c);
}
}
}
}
// 如果栈不为空,则将栈中所有元素出栈放到逆波兰链表的最后
while (!stack.isEmpty()) {
rpnList.add(stack.pop());
}
return rpnList;
}
/**
* 通过逆波兰表达式计算结果
*
* @return
*/
public static String calculate(String exp) {
Stack stack = new Stack();
List rpnList = Arithmetic.createRPN(exp);
int length = rpnList.size();
for (int i = 0; i < length; i++) {
String temp = (String) rpnList.get(i);
if (isNumber(temp)) {
stack.push(temp);
} else {
int number1 = Integer.parseInt(stack.pop());
int number2 = Integer.parseInt(stack.pop());
int rst = 0;
if (temp.equals(OP1)) {
rst = number1 + number2;
} else if (temp.equals(OP2)) {
rst = number2 - number1;
} else if (temp.equals(OP3)) {
rst = number2 * number1;
} else if (temp.equals(OP4)) {
rst = number2 / number1;
}
stack.push(Integer.toString(rst));
}
}
return stack.pop();
}
/**
* 获取逆波兰表达式字符串
*
* @return
*/
public static String getRPN(List rpnList) {
String rpn = "";
int rpnLength = rpnList.size();
for (int i = 0; i < rpnLength; i++) {
rpn += rpnList.get(i) + " ";
}
return rpn;
}
public static void main(String[] args) {
String str = "1+(2+3)*(100-5*(9+8))/5";
// 将四则运算字符串分解为逆波兰表达式后计算结果
System.out.println("result: " + Arithmetic.calculate(str));
}
}