0

私はこれをサーバーの応答として持っています:

"[(sin(1+3*4)+2)/7]+10"

この応答は、1、3、4、2、7、および10がDB(mysql)上のある種のインデックス項目であり、何度も評価する必要があることを意味します。私はJavaで良いライブラリを探していて、数式パーサーのようなexp4j、expr、jep、jevalを見つけましたが、サーバーがその文字列を提供するだけなので、これらの「インデックス」を取得するオプションがどこにあるのかわかりません。 DBで参照する必要のある「インデックス項目」を教えてはいけません。助けてください :(

追加:1、3、4、2、7、および10は変数です。これらの変数名は、DB内のインデックスであるため、取得する必要があります(必ずしも数値ではありません)。名前を取得したら、SQLクエリを作成して、その変数の実際の値を取得します。

こんな感じです...

ParseMath function = new ParseMath("[(sin(1+3*4)+2)/7]+10");
String[] variables = function.getVariables();

System.out.println(values) = 1, 3, 4, 2, 7, 10

以降...

String[] realValues = SqlQuery(variables);

for(int i=0; i<variables.lenght(); i++){
function.setValue(variable[i],realValue[i]);
}

double result = function.exec();

PS:私が書いた関数とメソッドは存在しません、私はそれを私の問題の文脈のように置きます...

4

2 に答える 2

2

ほとんどの式パーサーは、数値を数値として扱います。それらを変数として扱いたい場合は、それらを文字に置き換えるか接頭辞を付けます。つまり、次のようにします。

ParseMath function = new ParseMath(replaceVariables("[(sin(1+3*4)+2)/7]+10"));

ここで、replaceVariablesは次のようになります。

String replaceVariables(String expr) {
  StringBuilder sb = new StringBuilder();
  boolean wasDigit = false;
  for (int i = 0; i < expr.length; i++) {
    char c = sb.charAt(i);
    if (c >= '0' && c <= '9') {
      if (!wasDigit) {
        sb.append('x');
      }
      wasDigit = true;
    } else if (c == '[') {
      c = '(';
    } else if (c == ']') {
      c = ')';
    }
    sb.append(c);
  }
  return sb.toString();
}

((sin(x1+x3*x4)+x2)/x7)+x10これにより、式パーサーによって認識される可能性が高い式の例が変わります。

変数を設定するときに同じ変換を行う必要があることに注意してください。つまり、サーバーの応答が文字列配列realValuesにある場合は、次のように変数を設定する必要があります。

for (int i = 0; i < realValues.length; i++) {
  function.setValue("x" + i, Double.parseDouble(realValues[i]));
}
double result = function.exec();
于 2012-06-20T21:56:31.503 に答える
0

私は正規表現に少し錆びていますが、これを行うにはそれが最も効果的な方法だと思います。Regexは式内の変数と数値の名前を取得し、式libが提供する任意の機能を使用して、値を元に戻すことができます。サーバーが返すことができるすべての関数を知っておく必要があることに注意してください。それらを結果から除外します(変数のように見えます)。

public static void main( String[] args ) {
    String expression = "[(sin(1+3*4)+2)/7]+10";
    LinkedList<String> vars = new LinkedList<>();

    Pattern p = Pattern.compile("(?:[^0-9a-zA-Z]|\\G|^)([0-9a-zA-Z]+)(?:[^0-9a-zA-Z]|$)");
    Matcher m = p.matcher( expression );

    while(m.find()) {
        vars.add( m.group( 1 ) );
    }

    for(String s : vars ) {
        // Here's where you'd filter out the functions like "sin", "cos", etc.
        System.out.println( s );
    }
}

正規表現に穴がないことを確認するために、いくつかの例を使用してこれをテストすることをお勧めします。

于 2012-06-20T22:09:31.440 に答える