[JAVA]逆波蘭表示法(Reverse Polish Notation)計算算式

逆波蘭表示法(後綴表示法)
例如:
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!