字尾表示式的計算器Java實現
阿新 • • 發佈:2018-12-30
直接上程式碼
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));
}
}