La mejor y más corta forma de evaluar expresiones matemáticas

Hay muchos algoritmos para evaluar expresiones, por ejemplo:

  1. Por descenso recursivo
  2. Algoritmo de yarda de maniobra
  3. Notación polaca inversa

¿Hay alguna manera de evaluar cualquier expresión matemática usando la reflexión C # .net u otra tecnología .NET moderna?

Además de la respuesta de Thomas, en realidad es posible acceder a las bibliotecas JScript (obsoletas) directamente desde C #, lo que significa que puede usar el equivalente de la función de eval de JScript.

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

Ciertamente es posible. La clase CodeSnippetCompileUnit básicamente hace esto. Te escribí un ejemplo de código de uso. Deberá incluir estos espacios de nombres:

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

Aquí está el código:

 string source = @" class MyType { public static int Evaluate() { return ; } } "; string parameters = "int a, int b, int c"; string expression = "a + b * c"; string finalSource = source.Replace("", parameters).Replace("", 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 }); 

Reemplace ‘parámetros’ y ‘expresión’ por lo que sea, y obtendrá un evaluador de expresiones generales.

Si obtiene una excepción FileNotFoundException en results.CompiledAssembly, el fragmento no pudo comstackrse.

También es posible que desee echar un vistazo a la clase System.CodeDom.CodeSnippetExpression. Se usa para leer expresiones más específicamente, pero una expresión en sí misma no se puede comstackr, por lo que necesitaría usar más CodeDom para construir una clase trabajadora y un método a su alrededor. Esto es útil si desea poder manipular mediante progtwigción qué tipo de clase está generando. CodeSnippetCompileUnit es agradable para generar una clase trabajadora completa a la vez (y más simple para un ejemplo), pero para manipularla tendrías que hacer manipulaciones de cadenas inconvenientes.

Si bien el uso de servicios de comstackción es una solución simple y eficiente, plantea serios problemas de seguridad si un usuario ingresa la expresión, ya que podría ejecutar virtualmente cualquier cosa .

Hay otra solución muy simple que es mucho más segura: aproveche la función JScript Eval . Solo necesita seguir estos pasos:

Cree un archivo js llamado JsMath.js:

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

Comstackrlo en una biblioteca de clase:

 jsc /t:library JsMath.js 

Haga referencia a la biblioteca JsMath en su proyecto C # y úselo de esta manera:

 double result = JsMath.Eval(expression); 

Para mí, Vici.Parser funciona muy bien: compruébalo aquí , es el analizador de expresiones más flexible que he encontrado hasta ahora.

(Lo hemos usado para configurar reglas comerciales ‘legibles por humanos’, con datos proporcionados por una base de datos de servidor SQL)

Hay ejemplos disponibles y hay un muy buen soporte por parte del desarrollador (consulte el foro del sitio web).

ncalc es el mejor. puedes encontrarlo en codeplex también en nugget.
NCalc es un evaluador de expresiones matemáticas en .NET. NCalc puede analizar cualquier expresión y evaluar el resultado, incluidos los parámetros estáticos o dynamics y las funciones personalizadas.

Creo que esta es la mejor manera de todas. La respuesta de Petar Repac es increíble. El uso del argumento ‘expresión’ del objeto DataColumn resuelve increíble y fácilmente el tema:

 static double Evaluate(string expression) { var loDataTable = new DataTable(); var loDataColumn = new DataColumn("Eval", typeof(double), expression); loDataTable.Columns.Add(loDataColumn); loDataTable.Rows.Add(0); return (double)(loDataTable.Rows[0]["Eval"]); }