在写计算器应用程序时,我们需要通过四则运算表达式构造逆波兰表达式,通过逆波兰表达式进行求值。
<注:逆波兰表达式,也称后缀表达式>
算法:需要构造运算符栈,通过进栈、出栈将愿表达式转换成为所需的逆波兰表达式。
转换过程:
(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 expList = new ArrayList();
private List postfixList = new ArrayList();
栈的定义,不解释,见代码;
private class Stack
{
LinkedList stackList = new LinkedList();
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());
}
部分思想源于网上大牛! 多谢各位大牛指导!!!