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.
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.
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");
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);
}
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.
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.
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" />