记住前一位的加号或减号运算符,使用加号或减号用运算符后面的数字改变累加值。
package yuki.arithmetic.script; public class SingleDigitTest { public static void main(String[] args) { String s1 = "1+2+3+4+5+6+7+8+9"; System.out.println(s1 + "=" + calculate(s1)); String s2 = "1-2+3+4-5+6+7-8+9"; System.out.println(s2 + "=" + calculate(s2)); } private static int calculate(String s) { char[] cs = s.toCharArray(); char oper = '+'; int result = 0; for (int i = 0; i < cs.length; i++) { char c = cs[i]; if(c == '+' || c == '-'){ oper = c; }else if('0' <= c && c <= '9') { int x = c - '0'; switch (oper) { case '+': result += x; break; case '-': result -= x; break; } } } return result; } }
运行结果如下:
1+2+3+4+5+6+7+8+9=45 1-2+3+4-5+6+7-8+9=15
java提供的脚本解析工具,如果解析的脚本是javascript脚本,实现类是RhinoScriptEngine。
package yuki.arithmetic.script; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class ScriptEngineTest { public static void main(String[] args) throws ScriptException { ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("javascript"); String script = "1*2*3*4*5*6*7*8*9"; Object result = engine.eval(script); System.out.println(script + " = " + result); System.out.println(script + " = " + 1*2*3*4*5*6*7*8*9); } }
运行结果如下:
1*2*3*4*5*6*7*8*9 = 362880.0 1*2*3*4*5*6*7*8*9 = 362880
方便测试,上一行使用的是下文的四则运算解析,下一行使用的是javascript的脚本解析。
为了避免计算错误输入的脚本,所以在计算前做了去除空白字符,验证脚本是否输入规范。
从后往前的解析脚本,这与正常的计算顺序一致,因为使用了递归,都是把前面的结果算完了再和后面的结果操作。
如果是从前往后的解析脚本,途中出现减号,后面的算式作为一个括号中的整体参与减法,导致计算错误。
package yuki.arithmetic.script; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class ResolverDemo { public static void main(String[] args) throws ScriptException { String s1 = "1+2+(3+4)+(5+(6*7+8))+9"; System.out.println(calculate(read(s1))); System.out.println(evalScript(s1)); String s2 = "1+2+(3/4)+(5+(6*7+8/9))"; System.out.println(calculate(read(s2))); System.out.println(evalScript(s2)); String s3 = "((1+(2+(3/4))+(5+(6*78+9))))"; System.out.println(calculate(read(s3))); System.out.println(evalScript(s3)); String s4 = "1-(2-(3/4))+(5-(-6*7*8+9))"; System.out.println(calculate(read(s4))); System.out.println(evalScript(s4)); String s5 = "-12*3 + 4*56 - (7 + 8*9)/(2*3)"; System.out.println(calculate(read(s5))); System.out.println(evalScript(s5)); } public static Object evalScript(String script){ ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript"); try { return engine.eval(script); } catch (ScriptException e) { e.printStackTrace(); return -1; } } public static String read(String s){ s = s.replaceAll("//s+", ""); char[] cs = s.toCharArray(); for (int i = 0, j = 1; j < cs.length; ++i, ++j) if((cs[i] == '+' || cs[i] == '-' || cs[i] == '*' || cs[i] =='/') && (cs[j] == '+' || cs[j] == '-' || cs[j] == '*' || cs[j] =='/')) throw new RuntimeException("运算符相邻"); int deep = 0; for (char c : cs) { if(c == '(') ++ deep; else if(c == ')') -- deep; } if(deep != 0) throw new RuntimeException("左右括号不等"); return s; } public static double calculate(String s){ char[] cs = s.toCharArray(); if(cs.length == 0) return 0; int pos = -1; if((pos = plusPos(cs)) != -1){ char oper = cs[pos]; double left = calculate(s.substring(0, pos)); double right = calculate(s.substring(pos + 1)); if(oper == '+') return left + right; else if(oper == '-') return left - right; }else if((pos = timesPos(cs)) != -1){ char oper = cs[pos]; double left = calculate(s.substring(0, pos)); double right = calculate(s.substring(pos + 1)); if(oper == '*') return left * right; else if(oper == '/') return left / right; }else{ if(cs[0] == '(' && cs[cs.length - 1] == ')'){ return calculate(s.substring(1, cs.length - 1)); }else{ int y = 0; for (char c : cs) if('0' <= c && c <= '9') y = y*10 + (c - '0'); if(cs[0] == '-') y *= -1; return y; } } return 0; } private static int plusPos(char[] cs) { int deep = 0; for (int i = cs.length - 1; i >= 0 ; --i) { char c = cs[i]; switch (c) { case '(': ++deep; break; case ')': --deep; break; case '+': case '-': if(deep == 0) return i; break; } } return -1; } private static int timesPos(char[] cs) { int deep = 0; for (int i = cs.length - 1; i >= 0 ; --i) { char c = cs[i]; switch (c) { case '(': ++deep; break; case ')': --deep; break; case '*': case '/': if(deep == 0) return i; break; } } return -1; } }
运行结果如下:
74.0 74.0 51.638888888888886 51.638888888888886 485.75 485.75 331.75 331.75 174.83333333333334 174.83333333333334
本文地址: http://www.cnblogs.com/kodoyang/p/Arithmetic_ScriptResolve_Calculate.html
雨木阳子
2015年8月29日