直接上代码
package cn.john.cal;
/**
*
* @ClassName: Operators
*
* @Description: 操作符枚举
*
* @author: John
*
* @date: 2017年5月9日 下午22:05:16
*
*
*/
public enum OperatorsEnum {
PLUS(0, '+'), MINUS(0, '-'), MULTIPLY(1, '*'), DIVIDE(1, '/'), MODULAR(1, '%'), LEFT_BRACKET(2,
'('), RIGHT_BRACKET(2, ')');
public Integer prior;// 优先级
public Character operator;// 操作符
private OperatorsEnum(int prior, char operator) {
this.prior = prior;
this.operator = operator;
}
public String toString() {
return String.valueOf(operator);
}
}
package cn.john.cal;
import java.util.LinkedList;
import java.util.Scanner;
/**
*
* @ClassName: Cal
*
* @Description:
* <p>
* 基于后缀表达式的简易计算器,目前支持个位数加、减、乘、除、模和括号六种运算。
* <p>
* 中缀表达式->后缀表达式 操作符入栈
* <p>
* 后缀表达式->计算值 操作数入栈
*
* @author: John
*
* @date: 2017年5月9日 下午7:55:58
*
*/
public class Cal {
/**
* @Title: toPostFix
* @Description: 将中缀表达式转换为后缀表达式
* @param infix
* @return
* @return: String
*/
public String toPostFix(String infix) {
// 算式字符数组
char[] ch = infix.trim().toCharArray();
LinkedList<OperatorsEnum> stack = new LinkedList<OperatorsEnum>();
StringBuilder sb = new StringBuilder();
OperatorsEnum op = null;
for (int i = 0; i < ch.length; i++) {
// 对每个算式字符,检查它是不是操作符
if ((op = isOperator(ch[i])) == null) {
sb.append(ch[i]);
} else {
// 右括号
// 持续弹出栈顶元素直到遇到左括号,但是不输出左括号
if (op.equals(OperatorsEnum.RIGHT_BRACKET)) {
// 如果不是左括号,持续弹出并输出
while (!stack.peek().equals(OperatorsEnum.LEFT_BRACKET)) {
sb.append(stack.pop());
}
// 此时栈顶元素为左括号,直接弹出,不输出
stack.pop();
} else {
// 非右括号
// 1、弹出并输出所有高优先级或者同等优先级,直到遇到低优先级或者左括号为止
// 上面的弹出语句有可能将栈弹空,检查stack的size避免NPE
while (stack.size() > 0 && stack.peek().prior >= op.prior
&& !stack.peek().equals(OperatorsEnum.LEFT_BRACKET)) {
sb.append(stack.pop());
}
// 2、将当前操作符入栈
stack.push(op);
}
}
}
// 弹出所有栈中剩余操作符
while (stack.size() > 0) {
sb.append(stack.pop());
}
return sb.toString();
}
/**
* @Title: calc
* @Description: 计算后缀表达式的值
* @param postfix
* @return
* @return: double
*/
public double calc(String postfix) {
char[] ch = postfix.toCharArray();
LinkedList<Double> stack = new LinkedList<Double>();
OperatorsEnum op = null;
for (int i = 0; i < ch.length; i++) {
if ((op = isOperator(ch[i])) == null) {
// 不是操作符,将当前数值入栈
stack.push(Double.parseDouble(String.valueOf(ch[i])));
} else {
// 是操作符,进行计算
double b = stack.pop();
double a = stack.pop();
switch (op) {
case PLUS:
stack.push(a + b);
break;
case MINUS:
stack.push(a - b);
break;
case MULTIPLY:
stack.push(a * b);
break;
case DIVIDE:
stack.push(a / b);
break;
case MODULAR:
stack.push(a % b);
break;
default:
break;
}
}
}
return stack.pop();
}
/**
* @Title: isOperator
* @Description: 判断字符是否为操作符
* @param ch
* @return
* @return: OperatorsEnum
*/
private OperatorsEnum isOperator(char ch) {
for (OperatorsEnum op : OperatorsEnum.values()) {
if (ch == op.operator) {
return op;
}
}
return null;
}
// test
/**
* @Title: readEquation
* @Description: 终端输入算式
* @return
* @return: String
*/
public String readEquation() {
Scanner sc = new Scanner(System.in);
String equation = sc.nextLine();
sc.close();
return equation;
}
public static void main(String[] args) {
Cal c = new Cal();
System.out.println("Please input an equation,press ENTER to submit!");
String infix = c.readEquation();
String s = c.toPostFix(infix);
System.out.println("postfix: " + s);
System.out.println("Result: "+infix + "=" + c.calc(s));
}
}