web-dev-qa-db-ja.com

javaの代数方程式パーサー

方程式を解析して入力を与える結果を得ることができるライブラリが必要です。

たとえば、次のようなものです。

String equation = "x + y + z";
Map<String, Integer> vars = new HashMap<String, Integer>();
vars.add("x", 2);
vars.add("y", 1),
vars.add("z", 3);
EquationSolver solver = new EquationSolver(equation, vars);
int result = solver.getResult();
System.out.println("result: " + result);

そして評価する:6

Javaのために、私のためにそれを行うことができるライブラリはありますか?

ありがとう

18
Alfredo Osorio

Java 1.6のスクリプト機能を利用できます:

import javax.script.*;
import Java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
        Map<String, Object> vars = new HashMap<String, Object>();
        vars.put("x", 2);
        vars.put("y", 1);
        vars.put("z", 3);
        System.out.println("result = "+engine.eval("x + y + z", new SimpleBindings(vars)));
    }
}

これは以下を生成します:

result = 6.0

より複雑な式の場合、 [〜#〜] jep [〜#〜] が適切な選択です。

28
Bart Kiers

exp4j 、DijkstraのShuntingYardに基づく式エバリュエーターもあります。これは、Apache License 2.0の下で無料で入手および再配布でき、サイズはわずか25kbで、非常に使いやすいです。

Calculable calc = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
        .withVariable("x", varX)
        .withVariable("y", varY)
        .build()
double result1=calc.calculate();

exp4j にカスタム関数を使用する機能もあります。

exp4j-数式を評価する

楽しんで!

17
fasseg

高いパフォーマンスが必要な場合は、exp4jを使用しないことをお勧めします。CogitoLearningクラスはexp4j(100万回の反復でテスト)よりも約2600倍高速です。その権利を読んでください。

多くの場合、ビジネスアプリケーションには単純な式で十分です。したがって、CogitoLearningによって作成されたライブラリがおそらくより良い選択です。

ベンチマーク結果:

1000000 iterations to evaluate 200*(1+(pi/2))^2
Time Exp4J: 1.041117999977863E-5
Time JavaScript:4.532046999924487E-5 - 0.2297235664138545x slower than Exp4j
Time ExpCogit:  4.0000000000000036E-9 - 2602.794999944655x faster than Exp4j

Cogitoライブラリについては、 http://cogitolearning.co.uk/docs/cogpar/index.html を参照してください。

注:テストケースは、JavaScriptのパフォーマンスを評価するために完全に純粋ではありません。その場合、ビルド済みの式を使用しなかったためです。

使用されたベンチマークコード:

public class TestParser {
    private static String exprStr = "200*(1+(pi/2))^2";

    /**
     * Exp4j
     */ 
    private static ExpressionBuilder eb =  new ExpressionBuilder(exprStr);

    /**
     * Cogit
     */
    private static Parser parser = new Parser();
    private static ExpressionNode expr = parser.parse(exprStr);

    /**
     * JavaScript 
     */
    private static ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
    private static Map<String, Object> vars = new HashMap<String, Object>();

    public static void main(String[] args) throws UnknownFunctionException, UnparsableExpressionException, ScriptException {
        int n = 1000000;

        double t1 = 0d; 
        for(int i=1; i!=n; i++) {
            t1+=getCalcTimeExp4J();
        }
        double r1=t1/n;

        double t2 = 0d; 
        for(int i=1; i!=n; i++) {
            t2+=getCalcTimeCogit();
        }
        double r2=t2/n;

        double t3 = 0d; 
        for(int i=1; i!=n; i++) {
            t3+=getCalcTimeJavaScriptEngine();
        }
        double r3=t3/n;     

        System.out.println(n + " iterations to evaluate " + exprStr);
        System.out.println("Time Exp4J:\t" + r1);

        System.out.println("Time JavaScript:" + r3 + " - " + r1/r3 + "x slower than Exp4j");
        System.out.println("Time ExpCogit:\t" + r2 + " - " + r1/r2 + "x faster than Exp4j");

    }

    private static double getCalcTimeJavaScriptEngine() throws ScriptException {
        long t = Util.nanotime();

        vars.put("pi", Math.PI); 
        //Note that we're actually not using a pre-build expression here.
        engine.eval(exprStr, new SimpleBindings(vars)); 

        return(Util.nanotimeToSeconds(t));
    }

    private static double getCalcTimeCogit() {
        long t = Util.nanotime();

        expr.accept(new SetVariable("pi", Math.PI));
        double r = expr.getValue();

        return(Util.nanotimeToSeconds(t));
    }           

    private static double getCalcTimeExp4J() throws UnknownFunctionException, UnparsableExpressionException {
        long t = Util.nanotime();
        Calculable calc = eb.withVariable("pi", Math.PI).build();
        double r = calc.calculate();

        return(Util.nanotimeToSeconds(t));
    }
}
2
user3694437

mXparser を試してください。以下に使用例を示します。

import org.mariuszgromada.math.mxparser.*;
...
...
String equation = "x + y + z";
Argument x = new Argument("x = 2");
Argument y = new Argument("y = 1");
Argument z = new Argument("z = 3");
Expression solver = new Expression(equation, x, y, z);
double result1 = solver.calculate();
System.out.println("result 1: " + result1);
x.setArgumentValue(3);
y.setArgumentValue(4);
z.setArgumentValue(5);
double result2 = solver.calculate();
System.out.println("result 2: " + result2);

結果:

result 1: 6.0
result 2: 12.0

ここで、mXparserの利点は、mXparserが式を1回だけプリコンパイルし、引数値が変更された後、計算が非常に高速に実行されることです。

mXparserチュートリアルmXparser数学コレクションmXparser API に従ってください。

よろしく

1
Leroy Kegan

この質問が出されてから8年後:車輪の再発明をしたくないのであれば、そこには多くのエキゾチックな数学パーサーがあります。

私が何年も前に書いたものがあり、算術演算、方程式の解法、微分計算、積分計算、基本統計、関数/式の定義、グラフ化などをサポートしています。

その呼ばれる ParserNG とそのオープンソース。

式の評価は次のように簡単です。

_    MathExpression expr = new MathExpression("(34+32)-44/(8+9(3+2))-22"); 
    System.out.println("result: " + expr.solve());

    result: 43.16981132075472
_

または、変数を使用して簡単な式を計算します。

_ MathExpression expr = new MathExpression("r=3;P=2*pi*r;"); 
System.out.println("result: " + expr.getValue("P"));
_

または関数の使用:

_MathExpression expr = new MathExpression("f(x)=39*sin(x^2)+x^3*cos(x);f(3)"); 
System.out.println("result: " + expr.solve());

result: -10.65717648378352
_

または、特定のポイントで導関数を評価するには(舞台裏でシンボリック微分(数値ではない)を行うため、精度は数値近似の誤差によって制限されないことに注意してください):

_MathExpression expr = new MathExpression("f(x)=x^3*ln(x); diff(f,3,1)"); 
System.out.println("result: " + expr.solve());

 result: 38.66253179403897
_

これは、x = 3で1回x^3 * ln(x)を区別します。今のところ、区別できる回数は1回です。

または数値積分の場合:

_MathExpression expr = new MathExpression("f(x)=2*x; intg(f,1,3)"); 
System.out.println("result: " + expr.solve());

result: 7.999999999998261... approx: 8
_

このパーサーはかなり高速で、他にも多くの機能があります。

免責事項:ParserNGは私が作成したものです。

0
gbenroscience