「25 + [変数1] > [変数2]」という形式のやや複雑な式があります。
式を解析し、コールバックを使用して変数値を要求し、式の全体的な結果を計算するには、式評価器が必要です。何千もの変数があるため、コールバックでなければなりません。
通常の数学演算子だけでなく、「if」なども必要です。言語が豊富であるほど良いです。
私たちは好きな言語を使うことができます。誰にも提案はありますか?
「25 + [変数1] > [変数2]」という形式のやや複雑な式があります。
式を解析し、コールバックを使用して変数値を要求し、式の全体的な結果を計算するには、式評価器が必要です。何千もの変数があるため、コールバックでなければなりません。
通常の数学演算子だけでなく、「if」なども必要です。言語が豊富であるほど良いです。
私たちは好きな言語を使うことができます。誰にも提案はありますか?
Mono.CSharp.Evaluatorの使用を検討しましたか?これを適切に設定されたInteractiveBaseClassと組み合わせると、最小限の労力で非常にうまく機能するようです。
以下はMono2.11.1alphaを使用していることに注意してください。
using System;
using System.Diagnostics;
using Mono.CSharp;
using NUnit.Framework;
public class MonoExpressionEvaluator
{
[Test]
public void ProofOfConcept()
{
Evaluator evaluator = new Evaluator(new CompilerContext(new CompilerSettings(), new ConsoleReportPrinter()));
evaluator.InteractiveBaseClass = typeof (Variables);
Variables.Variable1Callback = () => 5.1;
Variables.Variable2Callback = () => 30;
var result = evaluator.Evaluate("25 + Variable1 > Variable2");
Assert.AreEqual(25 + Variables.Variable1 > Variables.Variable2, result);
Console.WriteLine(result);
}
public class Variables
{
internal static Func<double> Variable1Callback;
public static Double Variable1 { get { return Variable1Callback(); } }
internal static Func<double> Variable2Callback;
public static Double Variable2 { get { return Variable2Callback(); } }
}
}
少し遅いのは本当に残念です。たとえば、私のi7-m620では、これを10,000回実行するのに約8秒かかります。
[Test]
public void BenchmarkEvaluate()
{
Evaluator evaluator = new Evaluator(new CompilerContext(new CompilerSettings(), new ConsoleReportPrinter()));
evaluator.InteractiveBaseClass = typeof(Variables);
Variables.Variable1Callback = () => 5.1;
Variables.Variable2Callback = () => 30;
var sw = Stopwatch.StartNew();
for (int i = 1; i < 10000; i++)
evaluator.Evaluate("25 + Variable1 > Variable2");
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
00:00:07.6035024
.NETの速度で実行できるように、解析してILにコンパイルできれば素晴らしいのですが、それはちょっとした夢のように聞こえます...
[Test]
public void BenchmarkCompiledMethod()
{
Evaluator evaluator = new Evaluator(new CompilerContext(new CompilerSettings(), new ConsoleReportPrinter()));
evaluator.InteractiveBaseClass = typeof(Variables);
Variables.Variable1Callback = () => 5.1;
Variables.Variable2Callback = () => 30;
var method = evaluator.Compile("25 + Variable1 > Variable2");
object result = null;
method(ref result);
Assert.AreEqual(25 + Variables.Variable1 > Variables.Variable2, result);
Variables.Variable2Callback = () => 31;
method(ref result);
Assert.AreEqual(25 + Variables.Variable1 > Variables.Variable2, result);
var sw = Stopwatch.StartNew();
for (int i = 1; i < 10000; i++)
method(ref result);
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
00:00:00.0003799
ああ、私の。
IFのようなExcelのような式の構成が必要ですか?あなた自身のものをつくる!
[Test]
public void ProofOfConcept2()
{
Evaluator evaluator = new Evaluator(new CompilerContext(new CompilerSettings(), new ConsoleReportPrinter()));
evaluator.InteractiveBaseClass = typeof(Variables2);
Variables.Variable1Callback = () => 5.1;
Variables.Variable2Callback = () => 30;
var result = evaluator.Evaluate(@"IF(25 + Variable1 > Variable2, ""TRUE"", ""FALSE"")");
Assert.AreEqual("TRUE", result);
Console.WriteLine(result);
}
public class Variables2 : Variables
{
public static T IF<T>(bool expr, T trueValue, T falseValue)
{
return expr ? trueValue : falseValue;
}
}
NCalcをチェックしてください。これは .NET であり、要件をサポートする必要があります。
純粋な式エバリュエーターは、実際には非常に簡単に記述できます。
数十の言語で式評価者を示すこの SO 回答を参照してください。次のいずれかを適応させることができるはずです。
編集:誰がこれを壊したかは明らかにそこに行って解決策を調べませんでした. はい、ゴルフのルール (通常は「最小」) を満たすためにぎっしりと詰め込まれたものがたくさんありますが、それらのほとんどはアルゴリズムのクリアテキスト バージョンでかなり明確に説明されています。
うーん...言語が必要です。C#、VB.Net、IronPython、IronRuby などがあります。
正規表現を使用して開いている変数を単純に置き換えます (おそらく、前もってそれらを知っていて、string.Replace が必要な場合もあります)。次に、CodeDOM (C# または VB.Net の場合) を使用してスクリプトをコンパイルするか、DLR (IronPython、IronRuby) を使用します。コードをカプセル化するために使用するメソッド ラッパーに変数をメソッド パラメーターとして追加するだけで (CodeDOM の場合)、変数を DLR に挿入することもできます。どちらのバリアントも、少ない労力と信頼できる労力で、ビジネスでチームに実装しました。
緊急にコールバックを再要求する場合は、ValueOf(string) のような名前でプログラミング言語のホストと通信するメソッドの上のソリューションに追加してください。だからあなたは書くことができます
ValueOf("A") > ValueOf("B") - 10
楽しむ。
http://code.google.com/p/bc-expression/
ラムダまたはブロック コールバックを介して変数ルックアップを処理します。
数値、文字列、およびブール定数を理解します。
単項演算子 + - !
演算子 || && < <= == != >= > + - * / %
( ) でグループ化
構文エラーがある場合、 Expression::SyntaxError を発生させます。