2014-09-22 59 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; 
} 
}