2014-09-22 56 views
0

我做了一个String数学表达式解析器如下:转换数学函数的JavaScript函数在Java中

public class ExpSolver { 
    public String solve(String s){ 
     try { 
      ScriptEngineManager mgr = new ScriptEngineManager(); 
      ScriptEngine engine = mgr.getEngineByName("JavaScript"); 
      return engine.eval(s).toString(); 
     } catch (ScriptException ex) { 
      Logger.getLogger(ExpSolver.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     return "0"; 
    } 
    public static void main(String args[]){ 
     System.out.println(new ExpSolver().solve(new java.util.Scanner(System.in).nextLine())); 
    } 
} 

现在我也想添加代码解析数学函数,例如正弦,余弦,棕褐色, ^(力量),日志等等到我的节目。 什么是最好的和代码效率的解决方案呢?我看到过正则表达式,但无法在如此大的范围内做到这一点。

回答

1

如何通过Java的ScriptEngine使用math.js并使用这个表达式解析器?

下面的例子:

package org.mathjs; 

import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.MalformedURLException; 
import java.net.URL; 

import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 
import javax.script.ScriptException; 

public class MathJSDemo { 
    protected static String MATHJS_URL = 
      "http://cdnjs.cloudflare.com/ajax/libs/mathjs/1.0.1/math.js"; 

    protected ScriptEngine engine; 

    public MathJSDemo() throws MalformedURLException, ScriptException, IOException { 
     ScriptEngineManager manager = new ScriptEngineManager(); 
     engine = manager.getEngineByName ("js"); 

     engine.eval(new InputStreamReader(new URL(MATHJS_URL).openStream())); 
     engine.eval("var parser = math.parser();"); 
     engine.eval("var precision = 14;"); 
    } 

    public String eval (String expr) throws ScriptException { 
     String script = "math.format(parser.eval('" + expr + "'), precision);"; 
     return (String) engine.eval(script); 
    } 

    public static void main(String[] args) throws ScriptException, MalformedURLException, IOException { 
     MathJSUrl math = new MathJSDemo(); 
     System.out.println(math.eval("a = 4.5")); 
     System.out.println(math.eval("1.2 * (2 + a)")); 
     System.out.println(math.eval("5.08 cm in inch")); 
     System.out.println(math.eval("sin(45 deg)^2")); 
     System.out.println(math.eval("9/3 + 2i"));  
     System.out.println(math.eval("det([-1, 2; 3, 1])")); 
    } 
} 
+0

这很酷... – 2014-09-25 17:20:57

2

JavaScript已经支持使用Math object这些函数。你应该能够直接在你正在评估的JavaScript表达式中使用它。例如:

1 + Math.cos(2) * Math.pow(3,4) 

如果你不希望有包括Math前缀,你可以做一些替换的字符串传递给解释之前:

s = s.replace("sin", "Math.sin").replace("cos", "Math.cos")... 

对于稍微干净的代码你可以将替换物存储在地图中。在你的程序的顶层:

static Map<String, String> replacements = new HashMap<String, String>(); 
static { 
    replacements.put("sin", "Math.sin"); 
    replacements.put("cos", "Math.cos"); 
    replacements.put("tan", "Math.tan"); 
} 

当你做你的换人:

for (Map.Entry<String, String> r : replacements.entrySet()) { 
    // Use replaceAll here only if you want the Strings to be interpreted as regexes 
    s = s.replace(r.getKey(), r.getValue()); 
} 
+0

我知道。我想将数学函数转换为JavaScript函数。 – 2014-09-22 15:11:17

+0

例如sin(2 + 1)将被转换为Math.sin(2 + 1)以在JavaScript引擎中解析。 – 2014-09-22 15:12:09

+0

对不起,误解了你的问题。看看我编辑的答案。 – 2014-09-22 15:17:32

2

几个选项,这取决于你真正想做的事:

  1. 只需使用javascript内置数学函数
    engine.eval("Math.sin(Math.PI)"); 
    
  2. 建立你自己的数学函数

    public class MyMathObject { 
        public Double doSomeMath(Double a, Double b) { 
         return a*b; 
        } 
    } 
    
    // Create an instance of your math object and add it to the engine 
    MyMathObject myMathObject = new MyMathObject(); 
    engine.put("funkyMath", myMathObject); 
    
    // Go ahead and use it 
    engine.eval("funkyMath.doSomeMath(3.14159, 2)"); 
    
  3. 请执行以上任一操作,但将'Math'对象(或您自己的对象)隐藏到'user'中。

    为此,在javascript中,在全局范围内定义变量,该变量保存对您希望具有语法快捷方式的函数(或常量)的引用。

    // Define "shortcuts" 
    engine.eval("var sin = Math.sin"); 
    engine.eval("var PI = Math.PI");   
    // Actual expression to be evaluated  
    engine.eval("sin(PI)"); 
    
0

最后我解决了这个问题,下面的类:

import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 
import javax.script.ScriptException; 

/** 
* 
* @author Aniruddha Sarkar(c) 
* [email protected] 
*/ 
public class ExpSolver { 
String[] regx; 
public ExpSolver() { 
    regx=new String[]{ 
     "Math.abs",  // the absolute value of a 
     "Math.acos", // arc cosine of a 
     "Math.asin", // arc sine of a 
     "Math.atan", // arc tangent of a 
     "Math.atan2", // arc tangent of a/b 
     "Math.ceil", // integer closest to a and not less than a 
     "Math.cos",  // cosine of a 
     "Math.exp",  // exponent of a ("Math.E to the power a) 
     "Math.floor", // integer closest to a, not greater than a 
     "Math.log",  // log of a base e 
     "Math.max", // the maximum of a and b 
     "Math.min", // the minimum of a and b 
     "Math.pow", // a to the power b 
     "Math.random", // pseudorandom number 0 to 1 (see examples) 
     "Math.round", // integer closest to a (see rounding examples) 
     "Math.sin",  // sine of a 
     "Math.sqrt", // square root of a 
     "Math.tan" // tangent of a 
    }; 
} 
public String solve(String s,String p){ 
    for(String str:regx){ 
     s=s.replaceAll(str.substring(str.indexOf(".")+1), str); 
    } 
    int x; 
    while(s!=null){ 
     x=s.indexOf('^'); 
     if(x!=-1){ 
      StringBuilder xa=new StringBuilder(); 
      for(int i=x-1;i>=0;i--){ 
       char k=s.charAt(i); 
       if(Character.isDigit(k)||k=='.'||k=='E'){ 
        xa.append(k); 
       } 
       else if(i>0) 
        if(s.charAt(i-1)=='E'){ 
         xa.append(k); 
        } 
       else{ 
        if(k=='-'){ 
         if(i>0){ 
          int kdx=i-1; 
          if(kdx>0){ 
           char kt=s.charAt(kdx); 
           if(!(Character.isDigit(kt)||kt=='.')){ 
            xa.append(k); 
           } 
          } 
         } 
         else{ 
          xa.append(k); 
         } 
        } 

        break; 
       } 
      } 
      xa.reverse(); 
      StringBuilder xb=new StringBuilder(); 
          xb.append(s.charAt(x+1)); 
          for(int i=x+2;i<s.length();i++){ 
       char k=s.charAt(i); 
       if(Character.isDigit(k)||k=='.'||k=='E'||s.charAt(i-1)=='E'){ 
        xb.append(k); 
       } 
       else{ 
        break; 
       } 
      } 

      double a=Double.parseDouble(xa.toString()),b=Double.parseDouble(xb.toString()); 
      double r=Math.pow(a,b); 
      s=s.substring(0,x-xa.length())+((int)r==r?(int)r:r)+s.substring(x+xb.length()+1,s.length()); 
      continue; 
     } 
     break; 
    } 
    try { 
     ScriptEngineManager mgr = new ScriptEngineManager(); 
     ScriptEngine engine = mgr.getEngineByName("JavaScript"); 
     engine.put("x", Double.parseDouble(p)); 
     return round(Double.parseDouble(engine.eval(s).toString()))+""; 
    } catch (ScriptException ex) { 
     Logger.getLogger(ExpSolver.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    return "0"; 
} 
public static void main(String args[]){ 
    System.out.println(new ExpSolver().solve(new java.util.Scanner(System.in).nextLine(),"25")); 
} 
public static float round(double x){ 
    return ((float)Math.rint((x-0.05)*100))/100; 
} 
}