5

I need to know if there is any library out there that will allow me to, given a certain string representing a mathematical function, say, x^2+x+1, (don't care about how the string format, any will work for me) generates a C# func that will represent said function.

Bart Kiers
  • 166,582
  • 36
  • 299
  • 288
user1432653
  • 109
  • 1
  • 6
  • 1
    Are you talking about something like an `eval` function for C#? http://stackoverflow.com/questions/4629/how-can-i-read-the-properties-of-a-c-sharp-class-dynamically http://www.codeproject.com/Articles/11939/Evaluate-C-Code-Eval-Function – Tim S. Jun 02 '12 at 17:14
  • No, I am talking about a library that for example takes the string: x^2+x+1 and generate a c# func that given X evaluate it accordingly. – user1432653 Jun 02 '12 at 17:20
  • I mean PARSING MATHEMATICAL FUNCTIONS TO FUNC IN C#. – user1432653 Jun 02 '12 at 17:35

5 Answers5

11

Been using FLEE (Fast Lightweight Expression Evaluator) for a while now and it's been working great. They have a version that maintains most functionality for Silverlight as well. It's designed to do pretty much exactly what you're asking for and more.

http://flee.codeplex.com/

Flee is an expression parser and evaluator for the .NET framework. It allows you to compute the value of string expressions such as sqrt(a^2 + b^2) at runtime. It uses a custom compiler, strongly-typed expression language, and lightweight codegen to compile expressions directly to IL. This means that expression evaluation is extremely fast and efficient.

Given your example from your comment to evaluate x^2+x+1 (written in Notepad):

public Func<double, double> CreateExpressionForX(string expression)
{

    ExpressionContext context = new ExpressionContext();
    // Define some variables
    context.Variables["x"] = 0.0d;

    // Use the variables in the expression
    IDynamicExpression e = context.CompileDynamic(expression);


    Func<double, double> expressionEvaluator = (double input) =>
    {
        content.Variables["x"] = input;
        var result = (double)e.Evaluate();
        return result;
    }

    return expressionEvaluator;
}



Func<double, double> expression = CreateExpressionForX("x^2 + x + 1");

double result1 = expression(1); //3
double result2 = expression(20.5); //441.75
double result3 = expression(-10.5); //121.75

Func<double, double> expression2 = CreateExpressionForX("3 * x + 10");

double result4 = expression2(1); //13
double result5 = expression2(20.5); //71.5
double result6 = expression2(-10.5); //-21.5
Chris Sinclair
  • 22,858
  • 3
  • 52
  • 93
4

Take a look at the Roslyn API. It will allow you to compile strings at runtime

cordialgerm
  • 8,403
  • 5
  • 31
  • 47
  • nice, even though its, as far as I understand, very far from really working/being finished. Itll be interesting to see how the whole concept will integrate with the way we all use c#/vb.net – YavgenyP Jun 02 '12 at 17:32
2

You can use the CSharpCodeProvider class to compile code to a file/assembly and dynamically load the compiled assembly. Using the compiler from your program is described here. This Stackoverflow questions shows how to load the compiled assembly. Keep in mind that you need to wrap your function in a class to load and execute it later on.

Alternatively you can use CS-Script to do the dirty assembly compiling, loading and executing job.

Community
  • 1
  • 1
saintedlama
  • 6,838
  • 1
  • 28
  • 46
  • I mean PARSING MATHEMATICAL FUNCTIONS TO FUNC IN C#. – user1432653 Jun 02 '12 at 17:35
  • you could have mentioned this in your original question. this STILL can be solved pretty easily with expression trees, but i guess the tool provided by Chris Sinclair will do the job as good as. – YavgenyP Jun 02 '12 at 17:48
1

You can use the CodeDOM to dynamic compile a type, about this, here you can find a fluent interface to simply the writing of the code, e.g:

var compileUnit = new FluentCodeCompileUnit()
    .Namespace("Sample1")
                .Class("Program")
                    .Method(MemberAttributes.Public | MemberAttributes.Static, "Main").Parameter(typeof(string[]), "args")
                        .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hello Fluent CodeDom"))
                    .EndMethod

                    .Method(MemberAttributes.Public | MemberAttributes.Static, "Linq2CodeDomSupport").Parameter(typeof(string[]), "args")
                        .Stmt(ExprLinq.Expr(() => Console.WriteLine("Hello Linq2CodeDOM")))
                        .Declare(typeof(int), "random", ExprLinq.Expr(() => new Random().Next(10)))
                        .If((int random) => random <= 5)
                            .Stmt(ExprLinq.Expr(() => Console.WriteLine("Smaller or equal to 5.")))
                        .Else
                            .Stmt(ExprLinq.Expr(() => Console.WriteLine("Bigger than 5.")))
                        .EndIf
                    .EndMethod
               .EndClass
            .EndNamespace
        .EndFluent();

        var assembly = Helper.CodeDomHelper.CompileInMemory(compileUnit);
        assembly.GetType("Sample1.Program").GetMethod("Main").Invoke(null, new object[] { null });

I've to release on CodePlex a better fluent interface API that will use Roslyn also when it will be released in RTM.

Matteo Migliore
  • 925
  • 8
  • 22
0

This looks like a nice solution. Of course, it also can be solved with the usage of Expression Trees and a parse from strings to expressions, which later can be compiled (in run time), and executed.

YavgenyP
  • 2,113
  • 14
  • 11