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