Best and shortest way to evaluate mathematical expressions

There are many algorithms to evaluate expressions, for example:

  1. By Recursive Descent
  2. Shunting-yard algorithm
  3. Reverse Polish notation

Is there any way to evaluate any mathematical expression using C# .net reflection or other modern .net technology?


Solution 1:

Further to Thomas's answer, it's actually possible to access the (deprecated) JScript libraries directly from C#, which means you can use the equivalent of JScript's eval function.

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();

Solution 2:

It's certainly possible. The CodeSnippetCompileUnit class does basically this. I wrote you some example usage code. You'll need to include these namespaces:

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

Here's the code:

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

Replace 'parameters' and 'expression' by whatever, and you've got yourself a general expression evaluator.

If you get a FileNotFoundException in results.CompiledAssembly, then the snippet failed to compile.

You might also want to take a look at the System.CodeDom.CodeSnippetExpression class. It's used for more specifically reading expressions, but an expression by itself can't be compiled, so you would need to use more CodeDom to build a working class and method around it. This is useful if you want to be able to programmatically manipulate what kind of class you're generating. CodeSnippetCompileUnit is nice to generate an entire working class at once (and simpler for an example) but to manipulate it you would have to do inconvenient string manipulations.

Solution 3:

Although using compiler services is a simple and efficient solution, it raises serious security issues if the expression is entered by a user, because it could execute virtually anything.

There's another very simple solution that is much more secure : take advantage of the JScript Eval function. You just need to follow these steps :

Create a js file named JsMath.js :

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

Compile it into a class library :

jsc /t:library JsMath.js

Reference the JsMath library in your C# project, and use it like that :

double result = JsMath.Eval(expression);

Solution 4:

For me Vici.Parser works extremely well: check it out here , it's the most flexible expression parser I've found so far.

(we've used it to set up 'human-readable' business rules, with data provided by an SQL server database)

Examples are available and there's a very good support by the developer (check the website's forum).

Solution 5:

ncalc is the best. you can find it in codeplex also in nugget.
NCalc is a mathematical expressions evaluator in .NET. NCalc can parse any expression and evaluate the result, including static or dynamic parameters and custom functions.