逆波兰表达式的计算实现
昨天写着写着就差点睡着了,,,马上就要开始复习了,连着考三门啊亲,还是不好过的三门,不过小达还是打算把逆波兰表达式的专栏写完再去复习
。昨天的代码没有多少,而且注释上面应该讲解的很清楚了,照着小达手动总结的规则,应该能够很容易的实现吧。今天我们就在昨天已经转化的基础上,用代码来实现逆波兰表达式的计算过程。

还是那个例子
后缀表达式 : 9 , 3 , 2 , 1 , / , - , * , 1 , -
大家应该都还记得我们在这个专栏里第二篇讲的计算规则吧。
逆波兰表达式的计算其实很容易,只需要建立一个栈,里面存放数字,遇到运算符直接从数字栈里弹出数字进行计算,将结果压入栈中即可,运算完毕后,存留在数字栈中的那个数字即需要的结果.
如规则上面说的那样,我们先建立一个数字栈,用来存放操作数,下面上栈的代码:
/**
* 数字栈类
*/
public class MyNumStack {
private int maxNum; //栈的最大容量
private String[] stackArray; //用字符串数组来存储操作数
private int top; //栈顶元素的索引
public MyNumStack(int max){
maxNum = max;
stackArray = new String[maxNum];
top = -1;
}
public void push(String c){
stackArray[++top] = c;
}
public String pop(){
try{
return stackArray[top--];
}
catch(Exception e){
return "ERROR!";
}
}
public boolean isEmpty(){
return top == -1;
}
}
上面的栈和上篇博客用于转化的符号栈式差不多的,也是将数据封装好了,只给外面提供一点接口来使用,下面是用于计算的类,其中持有一个上篇博客讲到的change.java类实例,用于将中缀表达式转化为后缀表达式。
/**
* 主要的计算类
*
*/
public class CalculateResult {
private boolean num_flag = false; //记录是否出现了多位数
private boolean point_flag = false; //记录是否出现了小数点
private boolean hasPointFlag; //用来确定是有小数点
public String cal(String str){
Change change = new Change(str); //上篇博客提到过的转化类
MyNumStack mns = new MyNumStack(str.length()); //今天讲的数字栈
String result = change.doChange();
hasPointFlag = result.contains(".");
/**
* 取出后缀表达式中的每个字符
* 处理一遍数字
* 再处理一遍小数点
*/
for(int i = 0;i < result.length();i++){
String c = result.substring(i,i+1);
if(c.equals("_")) {
num_flag = false;
point_flag = false;
continue;
}
try{
dealNumber(c,mns); //对数字和小数点进行逻辑盘断与处理函数
dealOperator(c,mns); //对加减乘除逻辑处理及计算函数
}
catch(Exception e){
return "Error!";
}
}
/**
* 处理完之后
* 还在数字栈里的唯一数字
* 就是我们需要计算的结果
*/
if(!mns.isEmpty()){
String res = mns.pop();
if(res.endsWith("."))
res = res.substring(0,res.length()-1);
if(res.endsWith(".0"))
res = res.substring(0,res.length()-2);
return (res);
}
else
return "Error!";
}
/**
* 处理数字的方法
* 遇到小数点说明当前数字是上一个数字的低位
* 需要将其加入到之前的那个数字中去
*/
public void dealNumber(String c,MyNumStack mns){ //对数字和小数点进行逻辑盘断与处理
if(c.equals(".")||c.equals("0")||c.equals("1")||
c.equals("2")||c.equals("3")||c.equals("4")||
c.equals("5")||c.equals("6")||c.equals("7")||
c.equals("8")||c.equals("9")){
if(c.equals(".")){ //对小数点和数字处理
String top = mns.pop();
if(top.contains("."))
mns.push(top);
else
mns.push(top+".");
num_flag = false;
point_flag = true;
}
else {
if (num_flag) {
if(hasPointFlag){ //如果计算的数字里面有小数点,就用double计算,否则用integer计算
double re = Double.valueOf(mns.pop());
mns.push(String.valueOf(Math.abs(re) * 10 + Double.valueOf(c)));
}
else{
int re = Integer.valueOf(mns.pop());
mns.push(String.valueOf(Math.abs(re) * 10 + Integer.valueOf(c)));
}
}
else{
if(point_flag){
String a = mns.pop();
if(a.endsWith(".0"))
a = a.substring(0,a.length()-1);
mns.push(a+c);
}
else{
mns.push(c);
num_flag = true;
point_flag = false;
}
}
}
}
}
/**
* 处理运算符的函数
* 遇到运算符即可计算
* 后缀表达式已经将运算的先后处理好了
*/
public void dealOperator(String c,MyNumStack mns){
if(c.equals("+")||c.equals("-")) { //遇到计算符,从栈里面弹两个数来计算,结果放回栈中
num_flag = false;
point_flag = false;
String str_a = mns.pop();
String str_b = mns.pop();
double a = Double.valueOf(str_a);
double b = Double.valueOf(str_b);
if(c.equals("+"))
mns.push(String.valueOf(b+a));
if(c.equals("-"))
mns.push(String.valueOf(b-a));
}
if(c.equals("/")||c.equals("*")) {
num_flag = false;
point_flag = false;
double a = Double.valueOf(mns.pop()); //遇到计算符,从栈里面弹两个数来计算,结果放回栈中
double b = Double.valueOf(mns.pop());
if (c.equals("*"))
mns.push(String.valueOf(b * a));
if (c.equals("/"))
mns.push(String.valueOf(b / a));
}
}
}
最后在这个类中的数字栈中即为计算的结果。上面的代码是 android计算器上的一部分,在这里直接奉上全部的源码。大家可以看看哈。逆波兰表达式的专栏就到这里结束了。后面小达再有什么好东西都会和大家分享的~~~~~~再见咯