逆波蘭表示法(後綴表示法)
例如:
a+b => a b +
a+(b-c) => a b c - +
a+d*(b-c) => a d b c - * +
a=1+3 => a 1 3 + =
支援多位數、小括號、小數點 計算
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
// 中綴表示法
String infixExpression = "(0.3 +63)*4-5-1";
infixExpression = replaceAllBlank(infixExpression);
List<String> infixList = getInfixList(infixExpression);
List<String> suffixList = getSuffixList(infixList);
Double result = calculate(suffixList);
System.out.println("計算結果 = " + result);
}
/**
*
* @param list suffix expression items
* @return calculation result
*/
public static Double calculate(List<String> list) {
Stack<String> stack = new Stack<>();
Double res = 0d;
// loop list
for (String item: list) {
boolean matches = isDigits(item);
if (matches) {
// item is digit(>= 1 digit)
stack.push(item);
} else {
// item is operator
// the second item which is popped up from stack should be front(num1)
String num2 = stack.pop();
String num1 = stack.pop();
if ("+".equals(item)) {
res = Double.parseDouble(num1) + Double.parseDouble(num2);
} else if ("-".equals(item)) {
res = Double.parseDouble(num1) - Double.parseDouble(num2);
} else if ("*".equals(item)) {
res = Double.parseDouble(num1) * Double.parseDouble(num2);
} else if ("/".equals(item)) {
res = Double.parseDouble(num1) / Double.parseDouble(num2);
} else {
throw new RuntimeException("運算符錯誤!");
}
// parse res to String
stack.push("" + res);
}
}
return res;
}
public static List<String> getSuffixList(List<String> infixList) {
// create a operStack
Stack<String> operStack = new Stack<>();
// create a list to add caculating result, or operator
// thread safe
List<String> list = new CopyOnWriteArrayList<>();
for (String item: infixList) {
if (isDigits(item)) {
//1. is digits
list.add(item);
} else if ("(".equals(item)) {
//2. is "("
operStack.push(item);
} else if (")".equals(item)) {
//3. is ")"
while (!"(".equals(operStack.peek())) {
list.add(operStack.pop());
}
// let "(" pop up of operStack!!!
operStack.pop();
} else {
//4. the top value of operStack is more than "item" priority
while (operStack.size() > 0 && priority(operStack.peek()) >= priority(item)) {
list.add(operStack.pop());
}
// remember to push into operator after loop!!!
operStack.push(item);
}
}
// pop up the rest of value from operStack
while (operStack.size() > 0) {
list.add(operStack.pop());
}
return list;
}
/**
* priority
*/
private static final int ADD = 1;
private static final int SUB = 1;
private static final int MUL = 2;
private static final int DIV = 2;
/**
* 去除任意空白, \f\n\r\t\v
* @param str 待替換空白的字串
* @return
*/
public static String replaceAllBlank(String str) {
return str.replaceAll("\\s+", "");
}
private static Pattern pattern = Pattern.compile("^[.\\d]*$");
/**
* 判斷是否為數字(含多位數)
* @param ch
* @return
*/
public static boolean isDigits(String ch) {
return pattern.matcher(ch).matches();
}
/**
*
* @param infixExpression 中綴表示法字串
* @return 中綴表示法list
*/
public static List<String> getInfixList(String infixExpression) {
List infixList = new ArrayList();
int i = 0;
String digits = "";
while(i < infixExpression.length()) {
if (!isDigits(""+infixExpression.charAt(i))) {
// add operator to list
infixList.add(""+infixExpression.charAt(i));
i++;
} else {
// isDigits
digits = "";
while (i < infixExpression.length() && isDigits(""+infixExpression.charAt(i))) {
digits += ""+infixExpression.charAt(i);
i++;
}
// add number to list
infixList.add(digits);
}
}
return infixList;
}
/**
* 運算符優先級
* @param ch
* @return
*/
public static int priority(String ch) {
int priority = Integer.MIN_VALUE;
if ("+".equals(ch)) {
priority = ADD;
} else if ("-".equals(ch)) {
priority = SUB;
} else if ("*".equals(ch)) {
priority = MUL;
} else if ("/".equals(ch)) {
priority = DIV;
}
return priority;
}
}
如有敘述錯誤,還請不吝嗇留言指教,thanks!