2011-02-12 40 views
1

我們在格式半複雜的表達式:
「25 + [變量1]> [變量2]」表達評估爲C#/的Python /紅寶石

我們需要表達式評估解析表達式,並使用一個回調詢問變量值並計算出表達式的總體結果。由於存在數千個變量,因此必須進行回調。

我們需要平時的數學運算,但還搞什麼「如果」等更豐富的語言越好。

我們可以使用任何我們想要的語言。任何人有任何建議?

+0

什麼是主機語言? – dtb 2011-02-12 17:24:49

+3

除非您對該語言有確切的說明,否則我們所能做的就是建議語言實施的一般資源。即使如此,我們只是指出你有用的資源,因爲這是你的編譯器構建過程,而不是我們的;) – delnan 2011-02-12 17:25:27

回答

2

退房NCalc。它是.NET,應該支持你的需求。

1

純粹的表達式評估器其實很容易編寫。

參見該SO回答其示出了在十幾個漢語語言表達評估。你應該能夠適應這些之一:

Code Golf: Mathematical expression evaluator (that respects PEMDAS)

編輯:誰丁當作響這顯然沒有去和檢查的解決方案在那裏。是的,有一堆人擠滿了高爾夫規則(通常是「最小」),但其中大部分都用明文版本的算法進行了很明顯的解釋。

0

那麼......你需要一種語言。你有C#,VB.Net,IronPython,IronRuby等等。使用正則表達式(也許你甚至可以知道它們,只需要一個字符串.Replace),然後使用CodeDOM編譯腳本(用於C#或VB.Net)或使用DLR(IronPython,IronRuby) 。您可以簡單地將變量作爲方法參數添加到您用於封裝代碼的方法包裝中(對於CodeDOM),或者只是將變量注入到DLR中。 我們在業務團隊中以較少的努力和可靠的努力實施了這兩種變體。

當你迫切regquire回調,很好的補充其上方的編程語言的主機與像的valueOf(串)的名稱通信的方法解決方案。所以,你可以寫

的valueOf( 「A」)>的valueOf( 「B」) - 10

有樂趣。

0

http://code.google.com/p/bc-expression/

經由一個lambda或塊回調把手變量查找。

參透數字,字符串和布爾常量。

一元運算符+ - !

Operators || !& & < < = = = => => + - * /%

與分組()

引發一個表達式:: SyntaxError錯誤,如果有一個語法錯誤。

3

你有沒有考慮過使用Mono.CSharp.Evaluator?看起來,這與一個合適的InteractiveBaseClass集相結合,可以很好地完成這個技巧,只需很少的工作。

請注意,以下使用Mono 2.11.1 alpha。

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花費差不多8秒運行這個10000次:

[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

這將會是巨大的,如果我們能夠解析和編譯成IL,所以我們可以執行它在.NET的速度,但是這聽起來像一個有點白日夢...

[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-like表達結構嗎?建立你自己的!

[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; 
     } 
    }