最近准备在android上写一个计算器,发现根本不会写呀,于是就在网上找怎么求表达式的值,最后找到了一个后缀表达式转中缀表达式再计算的方法,也没看懂,正好在学数据结构的栈,发现里面正好有逆波兰表达法,于是就用java写了一个表达式计算。然后又改了个c++版.
首先是准备工作,在计算表达式之前,我们需要知道到底用什么方法才能计算,对于一个算术表达式(中缀表达式),我们需要先转换为逆波兰(后最表达式)后,才能进行计算,不知道的要自行学习了,不然就像我一样找到了代码却看不懂。
首先对于表达式如 “9.2+(3-1.1)*3+10/2” 我用String 保存起来,要想对它进行转化,首先要判断它到底是不是标准的表达式,于是就有:
/**
* 是否为算术表达式
*
* @param str
* @return
*/
private static boolean isExpression(String str) {
int flag = 0;
for (int i = 0; i < str.length() - 1; i++) {
char ch = str.charAt(i);
char chb = str.charAt(i + 1);
if ((!isNum(ch) && i == 0) && ch != '(' || !isNum(chb)
&& (i == str.length() - 2) && chb != ')') {
System.out.println("首尾不是数字---->" + ch + chb);
return false;
}
if ((ch == '.' && !isNum(chb)) || (!isNum(ch) && chb == '.')) {
System.out.println("小数点前后不是数字--->" + ch + chb);
return false;
}
if (isOperator(ch) && !isNum(chb) && chb != '(') {
System.out.println("运算符不是数字--->" + ch + chb);
return false;
}
if (isNum(ch) && !isOperator(chb) && chb != '.' && chb != ')'
&& !isNum(chb)) {
System.out.println("数字后不是运算符--->" + ch + chb);
return false;
}
if (ch == '(') {
flag++;
}
if (chb == ')') {
flag--;
}
}
if (flag != 0) {
System.out.println("括号不匹配--->");
return false;
}
return true;
}
对于标准的表达式就好办些了,但是还是没什么变化,想要把一个字符串算术表达式转化为后缀表达式,我需要先把它分解成数字和运算符,每个数字和运算符都放入String然后装入List里,了代码如下:
/**
* 分解表达式
*
* @param str
* @return
*/
private static List<String> resolveString(String str) {
List<String> list = new ArrayList<String>();
String temp = "";
for (int i = 0; i < str.length(); i++) {
final char ch = str.charAt(i);
if (isNum(ch) || ch == '.') {
char c = str.charAt(i);
temp += c;
} else if (isOperator(ch) || ch == ')') {
if (!temp.equals("")) {
list.add(temp);
}
list.add("" + ch);
temp = "";
} else if (ch == '(') {
list.add("" + ch);
}
if (i == str.length() - 1) {
list.add(temp);
}
}
return list;
}
好了,完成了三分之一,接下来就是重点了,就是把中缀表达式转化为后缀表达式,转换规则是:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分,若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低 与栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。当然,我们这里是要后缀表达式的,所以就把输出的内容放到List里了。直接代码
/**
* 中缀表达式转换后缀
*
* @param list
* @return
*/
private static List<String> nifix_to_post(List<String> list) {
Stack<String> stack = new Stack<String>();
List<String> plist = new ArrayList<String>();
for (String str : list) {
if (isDouble(str)) {
plist.add(str);
}
if (isStrOperator(str) && stack.isEmpty()) {
stack.push(str);