If I have a string with a valid math expression such as:
String s = "1 + 2 * 7";
Is there a built in library/function in .NET that will parse and evaluate that expression for me and return the result? In this case 15.
If I have a string with a valid math expression such as:
String s = "1 + 2 * 7";
Is there a built in library/function in .NET that will parse and evaluate that expression for me and return the result? In this case 15.
Strange that this famous and old question has not an answer that suggests the builtin DataTable.Compute
-"trick". Here it is.
double result = Convert.ToDouble(new DataTable().Compute("1 + 2 * 7", null));
The following arithmetic operators are supported in expressions:
+ (addition)
- (subtraction)
* (multiplication)
/ (division)
% (modulus)
More informations: DataColumn.Expression
at Expression Syntax.
You could add a reference to Microsoft Script Control Library (COM) and use code like this to evaluate an expression. (Also works for JScript.)
Dim sc As New MSScriptControl.ScriptControl()
sc.Language = "VBScript"
Dim expression As String = "1 + 2 * 7"
Dim result As Double = sc.Eval(expression)
Edit - C# version.
MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControl();
sc.Language = "VBScript";
string expression = "1 + 2 * 7";
object result = sc.Eval(expression);
MessageBox.Show(result.ToString());
Edit - The ScriptControl is a COM object. In the "Add reference" dialog of the project select the "COM" tab and scroll down to "Microsoft Script Control 1.0" and select ok.
Have you seen http://ncalc.codeplex.com ?
It's extensible, fast (e.g. has its own cache) enables you to provide custom functions and varaibles at run time by handling EvaluateFunction/EvaluateParameter events. Example expressions it can parse:
Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)");
e.Parameters["Pi2"] = new Expression("Pi * Pi");
e.Parameters["X"] = 10;
e.EvaluateParameter += delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());
It also handles unicode & many data type natively. It comes with an antler file if you want to change the grammer. There is also a fork which supports MEF to load new functions.
For anybody developing in C# on Silverlight here's a pretty neat trick that I've just discovered that allows evaluation of an expression by calling out to the Javascript engine:
double result = (double) HtmlPage.Window.Eval("15 + 35");
Yet another option now that Roslyn is available:
You can use CodeAnalysis.CSharp.Scripting library for this.
using Microsoft.CodeAnalysis.CSharp.Scripting;
using System;
namespace ExpressionParser
{
class Program
{
static void Main(string[] args)
{
//Demonstrate evaluating C# code
var result = CSharpScript.EvaluateAsync("System.DateTime.Now.AddDays(-1) > System.DateTime.Now").Result;
Console.WriteLine(result.ToString());
//Demonstrate evaluating simple expressions
var result2 = CSharpScript.EvaluateAsync(" 5 * 7").Result;
Console.WriteLine(result2);
Console.ReadKey();
}
}
}
nuget packages:
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Common" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.CSharp.Scripting" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Scripting" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Scripting.Common" version="1.1.1" targetFramework="net461" />
Actually there is kind of a built in one - you can use the XPath namespace! Although it requires that you reformat the string to confirm with XPath notation. I've used a method like this to handle simple expressions:
public static double Evaluate(string expression)
{
var xsltExpression =
string.Format("number({0})",
new Regex(@"([\+\-\*])").Replace(expression, " ${1} ")
.Replace("/", " div ")
.Replace("%", " mod "));
return (double)new XPathDocument
(new StringReader("<r/>"))
.CreateNavigator()
.Evaluate(xsltExpression);
}
Initially I used the c# wrapper for muparser. This was very fast. The only faster solution I know is exprtk. If you are looking for other solutions you can checkout the benchmark.
But in case of .Net you can use the builtin support to compile code at runtime. The idea is to have a "template" source file as e.g. embedded resource where you can replace the formula for the evaluation. Then you pass this prepared class-source-code to the compiler.
A basic template could look like this:
public class CSCodeEvaler
{
public double EvalCode()
{
return last = Convert.ToDouble(%formula%);
}
public double last = 0;
public const double pi = Math.PI;
public const double e = Math.E;
public double sin(double value) { return Math.Sin(value); }
public double cos(double value) { return Math.Cos(value); }
public double tan(double value) { return Math.Tan(value); }
...
Notice the %formula% where the expression will be put in.
To compile use the class CSharpCodeProvider. I do not want to put in the complete source here. But this answer might help:
After you have the in memory assembly loaded you can create an instance of your class and call EvalCode.
Recently I was using mXparser, which is a math parser library for .NET and JAVA. mXparser supports basic formulas as well as very fancy / complicated ones (including variables, functions, operators, iteration and recursion).
https://mxparser.codeplex.com/
A few usage examples:
Example 1:
Expression e = new Expression("1+2*7 + (sin(10) - 2)/3");
double v = e.calculate();
Example 2:
Argument x = new Argument("x = 5");
Expression e = new Expression("2*x+3", x);
double v = e.calculate();
Example 3:
Function f = new Function("f(x,y) = sin(x) / cos(y)");
Expression e = new Expression("f(pi, 2*pi) - 2", f);
double v = e.calculate();
Found recently - in case you would like to try the syntax (and see the advanced use case) you can download the Scalar Calculator app that is powered by mXparser.
Best regards
If you need very simple thing you can use the DataTable
:-)
Dim dt As New DataTable
dt.Columns.Add("A", GetType(Integer))
dt.Columns.Add("B", GetType(Integer))
dt.Columns.Add("C", GetType(Integer))
dt.Rows.Add(New Object() {12, 13, DBNull.Value})
Dim boolResult As Boolean = dt.Select("A>B-2").Length > 0
dt.Columns.Add("result", GetType(Integer), "A+B*2+ISNULL(C,0)")
Dim valResult As Object = dt.Rows(0)("result")
You can use Math-Expression-Evaluator library that I am author of. It supports simple expressions such as 2.5+5.9
, 17.89-2.47+7.16
, 5/2/2+1.5*3+4.58
, expressions with parentheses (((9-6/2)*2-4)/2-6-1)/(2+24/(2+4))
and expressions with variables:
var a = 6;
var b = 4.32m;
var c = 24.15m;
var engine = new ExpressionEvaluator();
engine.Evaluate("(((9-a/2)*2-b)/2-a-1)/(2+c/(2+4))", new { a, b, c});
You can also pass parameters as named variables:
dynamic dynamicEngine = new ExpressionEvaluator();
var a = 6;
var b = 4.5m;
var c = 2.6m;
dynamicEngine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6);
It supports .Net Standard 2.0 so can be used from .Net Core as well as .Net Full Framework projects and it doesn't have any external dependencies.
I would also have a look at Jace (https://github.com/pieterderycke/Jace). Jace is a high performance math parser and calculation engine that supports all the .NET flavors (.NET 4.x, Windows Phone, Windows Store, ...). Jace is also available through NuGet: https://www.nuget.org/packages/Jace
A simple math parser is quite easy to build, and requires only a few lines of code:
Take this flexible example:
class RPN
{
public static double Parse( Stack<string> strStk )
{
if (strStk == null || strStk.Count == 0 )
{
return 0;
}
Stack<double> numStk = new Stack<double>();
double result = 0;
Func<double, double> op = null;
while (strStk.Count > 0)
{
var s = strStk.Pop();
switch (s)
{
case "+":
op = ( b ) => { return numStk.Pop() + b; };
break;
case "-":
op = ( b ) => { return numStk.Pop() - b; };
break;
case "*":
op = ( b ) => { return numStk.Pop() * b; };
break;
case "/":
op = ( b ) => { return numStk.Pop() / b; };
break;
default:
double.TryParse(s, NumberStyles.Any, out result);
if (numStk.Count > 0)
{
result = op(result);
}
numStk.Push(result);
break;
}
}
return result;
}
}
....
var str = " 100.5 + 300.5 - 100 * 10 / 100";
str = Regex.Replace(str, @"\s", "", RegexOptions.Multiline);
Stack<string> strStk = new Stack<string>(
Regex.Split(str, @"([()*+\/-])", RegexOptions.Multiline).Reverse()
);
RPN.Parse(strStk);
To enable precedence by bracketing a stack of stacks will suffice, such as archived by recursion. Anything between brackets is put on a new stack. Finally you can support math operations in a clean readable fashion by lambdas.
There's no built-in solution, but there are easy ways to make it work.
There are at least two good new solutions for the problem now: using symbolic algebra AngouriMath or general purpose algorithm library Towel.
You can do
using AngouriMath;
Entity expr = "1 + 2 + sqrt(2)";
var answer = (double)expr.EvalNumerical();
(by default it computes in high-precision, might be useful too)
Or compile it
Entity expr = "1 + 2 + sqrt(2) + x + y";
Func<double, double, double> someFunc = expr.Compile<double, double, double>("x", "y");
Console.WriteLine(someFunc(3, 5));
so that it could be used in time-critical code.
Here you can do
using Towel.Mathematics;
var expression = Symbolics.Parse<double>("(2 + 2 * 2 - (2 ^ 4)) / 2");
Console.WriteLine(expression.Simplify());
which would directly compute your expression into double
.
Both can be installed via Nuget: AngouriMath, Towel.
I implemented an expression parser a few years ago and had published a version of it in GitHub and Nuget:Albatross.Expression recently. It contains a ExecutionContext class that can evaluate a set of expressions such as:
It also has built in circular reference check which is useful to avoid a stack overflow.
using System;
using static MathNet.Symbolics.SymbolicExpression;
using static System.Console;
using static System.Numerics.Complex;
using Complex = System.Numerics.Complex;
namespace MathEvaluator
{
class Program
{
static readonly Complex i = ImaginaryOne;
static void Main(string[] args)
{
var z = Variable("z");
Func<Complex, Complex> f = Parse("z * z").CompileComplex(nameof(z));
Complex c = 1 / 2 - i / 3;
WriteLine(f(c));
var x = Variable("x");
Func<double, double> g = Parse("x * x + 5 * x + 6").Compile(nameof(x));
double a = 1 / 3.0;
WriteLine(g(a));
}
}
}
Don't forget to load
<PackageReference Include="MathNet.Symbolics" Version="0.20.0" />
Try my matheval library on github
repo: https://github.com/matheval/expression-evaluator-c-sharp
namespace CalcExp
{
internal class Program
{
private static void Main(string[] args)
{
double res = Evaluate("4+5/2-1");
Console.WriteLine(res);
}
public static double Evaluate(string expression)
{
var xsltExpression =
string.Format("number({0})",
new Regex(@"([\+\-\*])").Replace(expression, " ${1} ")
.Replace("/", " div ")
.Replace("%", " mod "));
// ReSharper disable PossibleNullReferenceException
return (double)new XPathDocument
(new StringReader("<r/>"))
.CreateNavigator()
.Evaluate(xsltExpression);
// ReSharper restore PossibleNullReferenceException
}
}
}
Flee Fast Lightweight Expression Evaluator
Language Reference
Example :
Imports Ciloci.Flee
Imports Ciloci.Flee.CalcEngine
Imports System.Math
Dim ec As New Ciloci.Flee.ExpressionContext
Dim ex As IDynamicExpression
ec.Imports.AddType(GetType(Math))
ec.Variables("a") = 10
ec.Variables("b") = 40
ex = ec.CompileDynamic("a+b")
Dim evalData
evalData = ex.Evaluate()
Console.WriteLine(evalData)
The output : 50