public final class MathNumber { private MathNumber() { } public static String numberPattern = "[-]?[0-9]+([.][0-9]*)?"; public static Pattern pattern = Pattern.compile(numberPattern); public static Matcher match(String string) { Matcher match = pattern.matcher(string); if (match.find()) { return match; } throw new RuntimeException(string + " is not a number."); } }第二步就是告訴「孩子」,計算數學題的過程。
public static String eval(String string) { string = string.trim(); while (!isMathNumber(string)) {// 同一優先級的哪一個先找到算哪一個 System.out.println("求解算式:" + string); boolean found = false; for (MathInterface math : mathList) { Matcher matcher = math.match(string); if (matcher.find()) { String exp = matcher.group(); String sig = ""; if (exp.charAt(0) == '-' && matcher.start() != 0) {// 若是不是第一個數字,-號只能當運算符 sig = "+"; } System.out.println("發現算式:" + exp); String evalResult = math.eval(exp); string = string.substring(0, matcher.start()) + sig + evalResult + string.substring(matcher.end()); System.out.println(exp + "計算結果爲:" + evalResult + ",代回原式"); found = true; break; } } if (!found) { throw new RuntimeException(string + " 不是合法的數學表達式"); } } return string; }
addMathExpression(new Add()); addMathExpression(new Subtract()); addMathExpression(new Multiply()); addMathExpression(new Devide()); addMathExpression(new Minus()); addMathExpression(new Factorial()); addMathExpression(new Remainder()); addMathExpression(new Bracket()); addMathExpression(new Power()); Collections.sort(mathList, new MathComparator());因爲大同小異,就裏就只貼出來加法和括號的實現方式。
public class Add implements MathInterface { static String plusPattern = BLANK + MathNumber.numberPattern + BLANK + "[+]{1}" + BLANK + MathNumber.numberPattern + BLANK; static Pattern pattern = Pattern.compile(plusPattern); static Pattern plus = Pattern.compile(BLANK + "\\+"); @Override public Matcher match(String string) { return pattern.matcher(string); } @Override public int priority() { return 1; } @Override public String eval(String expression) { Matcher a = MathNumber.pattern.matcher(expression); if (a.find()) { expression = expression.substring(a.end()); } Matcher p = plus.matcher(expression); if (p.find()) { expression = expression.substring(p.end()); } Matcher b = MathNumber.pattern.matcher(expression); if (b.find()) { } return new BigDecimal(a.group()).add(new BigDecimal(b.group())) .toString(); } }
public class Bracket implements MathInterface { static String bracketPattern = BLANK + "[(]{1}[^(]*?[)]" + BLANK; static Pattern pattern = Pattern.compile(bracketPattern); @Override public Matcher match(String string) { return pattern.matcher(string); } @Override public int priority() { return Integer.MAX_VALUE; } @Override public String eval(String expression) { expression = expression.trim(); return MathEvaluation.eval(expression.substring(1, expression.length() - 1)); } }到目前爲止,咱們的程序「寶寶」已經學會數學計算了,出個題讓伊試試。
public static void main(String[] args) { String string = "1+2^(4/2)+5%2"; System.out.println("結果是 :" + MathEvaluation.eval(string)); }程序寶寶的作題過程以下:
求解算式:1+2^(4/2)+5%2 發現算式:(4/2) 求解算式:4/2 發現算式:4/2 4/2計算結果爲:2.00,代回原式 (4/2)計算結果爲:2.00,代回原式 求解算式:1+2^2.00+5%2 發現算式:2^2.00 2^2.00計算結果爲:4,代回原式 求解算式:1+4+5%2 發現算式:5%2 5%2計算結果爲:1,代回原式 求解算式:1+4+1 發現算式:1+4 1+4計算結果爲:5,代回原式 求解算式:5+1 發現算式:5+1 5+1計算結果爲:6,代回原式 結果是 :6呵呵,程序寶寶的作題過程和人的作題過程很是一致,並且程序實現也很是簡單易懂。神馬編譯原理,神馬中綴表達式都用不上。(執行效率與其它算法比較不必定高,僅用於驗證經過規則讓程序的處理能力加強,因爲沒有進行深刻測試,正則表達式和程序邏輯是否寫得嚴密沒有通過深刻驗證)
須要源碼的童鞋請到GIT上直接獲取代碼。 java
git地址:http://git.oschina.net/tinyframework/mathexp.git git