在java中将数学函数转换为javascript函数

时间:2014-09-22 14:57:48

标签: java regex math

我已经制作了一个String Mathematical表达式Parser,如下所示:

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()));
  }
}

现在我还想添加代码来解析我的程序中的sin,cos,tan,^(power),log等数学函数。 这样做的最佳和代码有效的解决方案是什么?我已经看过正则表达式但是我无法在如此大规模的情况下这样做。

4 个答案:

答案 0 :(得分: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());
}

答案 1 :(得分: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对象(或您自己的对象)。

    为此,在javascript中,在全局范围内定义变量,这些变量包含对期望具有语法快捷方式的函数(或常量)的引用。

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

答案 2 :(得分:1)

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

这是一个例子:

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])"));
    }
}

答案 3 :(得分: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)
 * sarkar4540@gmail.com
 */
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;
}
}