简体   繁体   English

C#编译数值表达式

[英]C# compile numerical expression

Assume I allow the user to input a arbitrary numerical expression that allows usage of the explicit set of functions and predefined variables. 假设我允许用户输入一个任意的数值表达式,该表达式允许使用一组明确的函数和预定义变量。

Interpreting this is pretty straight forward but what if performance is a critical factor? 解释这一点很简单,但是如果性能是关键因素呢?

I need a way to compile (in runtime) a string with a expression into something that can be executed 20K times with different values on the variables. 我需要一种方法(在运行时)将带有表达式的字符串编译为可以在变量上具有不同值的情况下执行20K次。

So really you want to parse the string into (eventually) a typed delegate. 因此,实际上您想将字符串解析为(最终)类型化的委托。

One option, then it to parse the string into an Expression , which you can then compile to a lambda. 一个选项,然后它将字符串解析为Expression ,然后可以将其编译为lambda。 This is quite complex, but I have some code that will do much of this - but there may be existing parsers that already do the job in full. 这是相当复杂的,但是我有一些代码可以完成很多工作-但是可能已有现有的解析器已经完全完成了这项工作。

As a trivial Expression example: 作为一个简单的Expression示例:

    var x = Expression.Parameter(typeof(double), "x");
    var y = Expression.Parameter(typeof(double), "y");
    var body = Expression.Multiply(x, y);
    var func = Expression.Lambda<Func<double, double,double>>(body, x, y).Compile();

    double z = func(123.45, 678.90);

The problem is the rest of the parsing code ;-p 问题是其余的解析代码;-p

I wrote a string to Expression parser last week, but it is more code than I'd normally post here... over 300 lines (not including recognition of bespoke external functions, or named arguments (it currently uses anonymous "?" place-holders)). 我上周向Expression解析器写了一个string ,但是它的代码比我通常在此处发布的要多。...300行以上(不包括定制的外部函数或命名参数的识别(当前使用匿名“?”位置-持有人))。

but if (as you say) interpreting is easy, then perhaps use similar code to write an Expression that you can compile? 但是,如果(如您所说)解释很容易,那么也许使用类似的代码编写可以编译的Expression

Linq Samples by Microsoft already contain implementation of extensible Linq parser. Microsoft的Linq Samples已经包含可扩展的Linq解析器的实现。

sealed class Order
{
  public double SubTotal { get; set; }
  public double Shipping { get; set; }
}
static void Main()
{
  var calculateTotal = DynamicExpression
    .ParseLambda<Order, double>("SubTotal*@0+Shipping", 0.12)
    .Compile();

  var order = new Order
  {
    SubTotal = 124.99,
    Shipping = 7.99
  };
  Console.WriteLine(calculateTotal(order));
  Console.ReadLine();
}

You can check out the DbLinq project for sources or this post for more details: Dynamic Linq and Expression Parsing in .NET as a hint of C# compiler extensibility 您可以查看DbLinq项目中的源代码或这篇文章以了解更多详细信息: .NET中的动态Linq和表达式解析作为C#编译器可扩展性的提示

In C# 4.0, it'll become very easy and straightforward. 在C#4.0中,它将变得非常容易和直接。 However, before C# 4.0, I suggest you use Microsoft.JScript libraries to accomplish it. 但是,在C#4.0之前,建议您使用Microsoft.JScript库来完成它。

This is all you want: http://www.odetocode.com/Articles/80.aspx 这就是您想要的一切: http : //www.odetocode.com/Articles/80.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM