您的位置:首页 > 编程语言 > Java开发

java 逆波兰表达式 (后缀表达式) 计算器

2012-04-06 16:31 411 查看
在写计算器应用程序时,我们需要通过四则运算表达式构造逆波兰表达式,通过逆波兰表达式进行求值。


<注:逆波兰表达式,也称后缀表达式>

算法:需要构造运算符栈,通过进栈、出栈将愿表达式转换成为所需的逆波兰表达式。

转换过程:

(1)从左到右,依次读入,若读入字符是数字,则将其输出到逆波兰表达式列表。

(2)若读入字符是 '(' , 直接入栈;

若是 ‘)’,则采取出栈操作并顺序输出,直到 遇到第一个‘(‘ , ’(‘出栈不输出;

(3)若为其他运算符,则比较 栈顶元素 与 该优先符 优先级;

当栈顶元素优先级 >= 当前元素优先级,出栈并顺序输出栈内运算符,直到栈顶元素优先

级 < 当前元素优先级,将当前的运算符入栈。

若当前运算符优先级 > 栈顶运算符优先级, 直接入栈即可。

(4)扫描结束,顺序输出栈内元素,添至逆波兰表达式列表尾处即可。

附带实现代码:

基本定义:
private final static String OPER1 = "+";
private final static String OPER2 = "-";
private final static String OPER3 = "*";
private final static String OPER4 = "/";
private final static String OPERLEF = "(";
private final static String OPERRIGHT = ")";
private String exp;
private int precision = 4;             // 精度计算
private RoundingMode roundingmode = RoundingMode.HALF_UP;
private List<String> expList = new ArrayList<String>();
private List<String> postfixList = new ArrayList<String>();


栈的定义,不解释,见代码;

private class Stack
{
LinkedList<String> stackList = new LinkedList<String>();
public Stack()
{}

public boolean isEmpty()
{
return stackList.isEmpty();
}
public void push(String expession)
{
stackList.addLast(expession);
}

public String pop()
{
return stackList.removeLast();
}

public String top()
{
return stackList.getLast();
}
}
依次为判断是否是 ’)‘ ,’(‘,数字,以及优先级高低:

public boolean isNum(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(".");
}

/**The method using for judge whether
* a char is a 'x' or a '/'
* */

private boolean isHigher(String str)
{
if(str.equals(OPER3)||str.equals(OPER4))
{
return true;
}
else
{
return false;
}
}

/** The method using for judge whether the
* priority if str1 is higher than the str2
* */

private boolean compare(String str1, String str2)
{
if(str1.equals(OPERLEF))
{
return false;
}
if((!isHigher(str1))&&(isHigher(str2)))
{
return false;
}
else
{
if(isHigher(str1))
{
return true;
}
else
{
return false;
}
}
}

/** The method using for judge the
* '('*/

private boolean isLeft(String str)
{
return str.equals(OPERLEF);
}

/**The method using for judge the
* ')'*/
private boolean isRight(String str)
{
return str.equals(OPERRIGHT);
}


实现 四则运算的数字与运算符的分离,放入字符串内,后转换成后缀表达式,之后对后缀表达式进行计算。

private void seperate()
{
int length = exp.length();
String tempStr = "";
for(int i = 0; i < length; i++)
{
String tempChar = exp.substring(i,i+1);
if(isNum(tempChar))
{
tempStr += tempChar;
}
else
{
if(!tempStr.equals(""))
{
expList.add(tempStr);
}
expList.add(tempChar);
tempStr = "";
}
}
if(!tempStr.equals(""))
{
expList.add(tempStr);
}
}

/** The method using the expression list to
* convert a poxfixExpression
* return a poxfixList
* */

private void convertPoxfix()
{
Stack stack = new Stack();
int length = expList.size();
for(int i= 0; i < length; i++)
{
String ch = expList.get(i);
if(isNum(ch))
{
postfixList.add(ch);
}
else
{
if(isLeft(ch))
{
stack.push(ch);
}
else
if(isRight(ch))
{
while(!stack.isEmpty())
{
String tempChar = stack.pop();
if(!tempChar.equals(OPERLEF))
{
postfixList.add(tempChar);
}
else
{
break;
}
}
}
else
{
if(stack.isEmpty())
{
stack.push(ch);
}
else
{
if(compare(stack.top(),ch))
{
while(!stack.isEmpty() && compare(stack.top(),ch))
{
postfixList.add(stack.pop());
}
}
stack.push(ch);
}

}
}
}
while(!stack.isEmpty())
{
postfixList.add(stack.pop());
}
}

/**The method using for the calculation on the decimal precision
* */
public static BigDecimal getBigDecimal(String numString, int precision, RoundingMode roundingmode)
{
String precisionFlag = "0";
if(numString == null || numString.equals(""))
{
precisionFlag = "0.00";
}
else
{
precisionFlag = numString;
}

BigDecimal bigdecimal = new BigDecimal(precisionFlag);
bigdecimal.setScale(precision, roundingmode);
return bigdecimal;
}

/**the method which uses the postifixExpression to calculate
* the expression
* return the answer which is on the top of the stack
* */

public String calculation() throws ArithmeticException
{
Stack numStack = new Stack();
int length = postfixList.size();
for(int i = 0; i < length; i++)
{
String tempC = postfixList.get(i);

if(isNum(tempC))
{
numStack.push(tempC);
}
else
{
BigDecimal tempNum1 = getBigDecimal(numStack.pop(),precision,roundingmode);
BigDecimal tempNum2 = getBigDecimal(numStack.pop(),precision,roundingmode);
BigDecimal tempNum = getBigDecimal("",precision,roundingmode);

if(tempC.equals(OPER1))
{
tempNum = tempNum2.add(tempNum1);
}
else
if(tempC.equals(OPER2))
{
tempNum = tempNum2.subtract(tempNum1);
}
else
if(tempC.equals(OPER3))
{
tempNum = tempNum2.multiply(tempNum1);
}
else
if(tempC.equals(OPER4))
{
tempNum = tempNum2.divide(tempNum1, precision, roundingmode);
}
numStack.push(tempNum.toString());
}
}
return numStack.pop();
}
类的构造:

public PostfixExp(String exp, int precision, RoundingMode roundingmode)
{
this.exp = exp;
this.precision = precision;
this.roundingmode = roundingmode;
seperate();
convertPoxfix();

}


测试代码:

public String getPostfix()
{
String post = "";
int length = postfixList.size();
for(int i = 0; i < length; i++)
{
post += postfixList.get(i)+" ";
}
return post;
}


public static void main(String[] args)
{
String str = "1+4/2*3+5+(3+1)+2/2";
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
PostfixExp postfixexp = new PostfixExp(str,10,RoundingMode.HALF_UP);
String post = postfixexp.getPostfix();
System.out.println("PostFix Expression: "+ post);
System.out.println("Answer : "+ postfixexp.calculation());
}


至此 所有源代码已经给出,欢迎批评指正!!

部分思想源于网上大牛! 多谢各位大牛指导!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: