Pregunta

Hay muchos algoritmos para evaluar expresiones, por ejemplo:

  1. Por descenso recursivo
  2. Algoritmo de patio de maniobras
  3. Notación polaca inversa

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

¿Fue útil?

Solución

Además de la respuesta de Thomas, en realidad es posible acceder a las bibliotecas JScript (en desuso) directamente desde C #, lo que significa que puede usar el equivalente de la función 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();

Otros consejos

Ciertamente es posible. La clase CodeSnippetCompileUnit hace básicamente esto. Te escribí un código de uso de ejemplo. 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(<!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 });

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

Si obtiene una FileNotFoundException en los resultados. CompiledAssembly, entonces el fragmento no pudo compilarse.

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 compilar, por lo que necesitaría usar más CodeDom para construir una clase de trabajo y un método a su alrededor. Esto es útil si desea poder manipular mediante programación qué tipo de clase está generando. CodeSnippetCompileUnit es bueno para generar una clase de trabajo completa a la vez (y más simple, por ejemplo), pero para manipularlo, tendría que hacer manipulaciones de cadenas inconvenientes.

Si bien el uso de servicios de compilació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 prácticamente 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);
    };
}

Compilarlo en una biblioteca de clase:

jsc /t:library JsMath.js

Consulte la biblioteca JsMath en su proyecto de C # y úsela así:

double result = JsMath.Eval(expression);

Para mí, Vici.Parser funciona extremadamente bien: échale un vistazo aquí , es El analizador de expresiones más flexible que he encontrado hasta ahora.

(lo hemos usado para configurar reglas de negocio 'legibles por humanos', con datos proporcionados por una base de datos del 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. puede 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 dinámicos 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"]);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top