17

式を評価するアルゴリズムは多数あります。たとえば、次のとおりです。

  1. 再帰的降下による
  2. 操車場アルゴリズム
  3. 逆ポーランド記法

C# .net リフレクションまたはその他の最新の .net テクノロジを使用して数式を評価する方法はありますか?

4

8 に答える 8

19

Thomas の回答に加えて、(非推奨の) JScript ライブラリに C# から直接アクセスすることは実際には可能です。これは、JScript のeval機能と同等のものを使用できることを意味します。

using Microsoft.JScript;        // needs a reference to Microsoft.JScript.dll
using Microsoft.JScript.Vsa;    // needs a reference to Microsoft.Vsa.dll

// ...

string expr = "7 + (5 * 4)";
Console.WriteLine(JScriptEval(expr));    // displays 27

// ...

public static double JScriptEval(string expr)
{
    // error checking etc removed for brevity
    return double.Parse(Eval.JScriptEvaluate(expr, _engine).ToString());
}

private static readonly VsaEngine _engine = VsaEngine.CreateEngine();
于 2009-09-17T13:15:40.207 に答える
13

それは確かに可能です。CodeSnippetCompileUnitクラスは基本的にこれを行います。使用コードの例をいくつか書きました。次の名前空間を含める必要があります。

  • System.CodeDom.Compiler;
  • System.CodeDom;
  • Microsoft.CSharp;
  • System.Reflection;

コードは次のとおりです。

string source = @"
class MyType
{
    public static int Evaluate(<!parameters!>)
    {
        return <!expression!>;
    }
}
";

string parameters = "int a, int b, int c";
string expression = "a + b * c";

string finalSource = source.Replace("<!parameters!>", parameters).Replace("<!expression!>", expression);

CodeSnippetCompileUnit compileUnit = new CodeSnippetCompileUnit(finalSource);
CodeDomProvider provider = new CSharpCodeProvider();

CompilerParameters parameters = new CompilerParameters();

CompilerResults results = provider.CompileAssemblyFromDom(parameters, compileUnit);

Type type = results.CompiledAssembly.GetType("MyType");
MethodInfo method = type.GetMethod("Evaluate");

// The first parameter is the instance to invoke the method on. Because our Evaluate method is static, we pass null.
int result = (int)method.Invoke(null, new object[] { 4, -3, 2 });

'parameters' と 'expression' を何にでも置き換えれば、一般的な式エバリュエーターを手に入れることができます。

results.CompiledAssembly で FileNotFoundException が発生した場合、スニペットはコンパイルに失敗しています。

System.CodeDom.CodeSnippetExpression クラスも参照してください。式をより具体的に読み取るために使用されますが、式自体をコンパイルすることはできないため、より多くの CodeDom を使用して、その周りの作業クラスとメソッドを構築する必要があります。これは、生成するクラスの種類をプログラムで操作できるようにする場合に便利です。CodeSnippetCompileUnit は、作業クラス全体を一度に生成するのに適しています (例としてはより単純です) が、それを操作するには不便な文字列操作を行う必要があります。

于 2009-09-17T11:49:59.553 に答える
3

コンパイラサービスの使用はシンプルで効率的なソリューションですが、式が実質的に何でも実行される可能性があるため、ユーザーが式を入力すると、重大なセキュリティ問題が発生します。

より安全な別の非常に単純なソリューションがあります。JScriptEval関数を利用します。次の手順に従う必要があります。

JsMath.jsという名前のjsファイルを作成します。

class JsMath
{
    static function Eval(expression : String) : double
    {
        return eval(expression);
    };
}

それをクラスライブラリにコンパイルします:

jsc /t:library JsMath.js

C#プロジェクトでJsMathライブラリを参照し、次のように使用します。

double result = JsMath.Eval(expression);
于 2009-09-17T12:20:34.297 に答える
3

私にとって、Vici.Parser は非常にうまく機能します。ここで確認してください。これは、これまでに見つけた中で最も柔軟な式パーサーです。

(これを使用して、SQL サーバー データベースによって提供されるデータを使用して、「人間が判読できる」ビジネス ルールを設定しました)

例が利用可能であり、開発者による非常に優れたサポートがあります (Web サイトのフォーラムを確認してください)。

于 2009-09-17T12:43:18.270 に答える
3

ncalcは最高です。ナゲットでもコードプレックスで見つけることができます。
NCalc は、.NET の数式エバリュエーターです。NCalc は、任意の式を解析し、静的または動的パラメーターとカスタム関数を含む結果を評価できます。

于 2012-10-30T21:19:28.367 に答える
1

私はこれが最善の方法だと思います。Petar Repac の答えは素晴らしいです。DataColumn オブジェクトの 'expression' 引数を使用すると、トピックを信じられないほど簡単に解決できます。

static double Evaluate(string expression)
{
    var loDataTable = new DataTable();
    var loDataColumn = new DataColumn("Eval", typeof(double), expression);
    loDataTable.Columns.Add(loDataColumn);
    loDataTable.Rows.Add(0);
    return (double)(loDataTable.Rows[0]["Eval"]);
}
于 2014-09-24T22:06:06.960 に答える