Melhor e menor caminho para avaliar expressões matemáticas

Existem muitos algoritmos para avaliar expressões, por exemplo:

  1. Por descida recursiva
  2. Algoritmo Shunting-yard
  3. Notação polonesa reversa

Existe alguma maneira de avaliar qualquer expressão matemática usando C # .net reflection ou outra tecnologia moderna .net?

    Além da resposta de Thomas, é realmente possível acessar as bibliotecas JScript (obsoletas) diretamente de C #, o que significa que você pode usar o equivalente da function eval do 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(); 

    Certamente é possível. A class CodeSnippetCompileUnit basicamente faz isso. Eu escrevi a você um exemplo de código de uso. Você precisará include esses namespaces:

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

    Aqui está o 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 }); 

    Substitua ‘parameters’ e ‘expression’ por qualquer coisa, e você terá um avaliador de expressão geral.

    Se você obtiver um FileNotFoundException em results.CompiledAssembly, o snippet não pôde ser compilado.

    Você também pode querer dar uma olhada na class System.CodeDom.CodeSnippetExpression. É usado para ler mais especificamente expressões, mas uma expressão por si só não pode ser compilada, então você precisaria usar mais CodeDom para construir uma class de trabalho e método em torno dela. Isso é útil se você quiser manipular programaticamente o tipo de class que está gerando. CodeSnippetCompileUnit é legal para gerar uma class de trabalho inteira de uma vez (e mais simples para um exemplo), mas para manipulá-la você teria que fazer manipulações inconvenientes de string.

    Embora o uso de serviços de compilador seja uma solução simples e eficiente, ele gera sérios problemas de segurança se a expressão for inserida por um usuário, pois ele pode executar praticamente qualquer coisa .

    Há outra solução muito simples que é muito mais segura: aproveite a function JScript Eval . Você só precisa seguir estes passos:

    Crie um arquivo js chamado JsMath.js:

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

    Compile em uma biblioteca de classs:

     jsc /t:library JsMath.js 

    Faça referência à biblioteca JsMath em seu projeto C # e use-a assim:

     double result = JsMath.Eval(expression); 

    Para mim Vici.Parser funciona muito bem: confira aqui , é o analisador de expressões mais flexível que encontrei até agora.

    (nós o usamos para configurar regras de negócios ‘legíveis por humanos’, com dados fornecidos por um database do servidor SQL)

    Exemplos estão disponíveis e há um suporte muito bom por parte do desenvolvedor (verifique o fórum do site).

    ncalc é o melhor. você pode encontrá-lo no code – code também no nugget.
    NCalc é um avaliador de expressões matemáticas em .NET. O NCalc pode analisar qualquer expressão e avaliar o resultado, incluindo parâmetros estáticos ou dynamics e funções personalizadas.

    Eu acho que esse é o melhor jeito de todos. A resposta da Petar Repac é incrível. Usar o argumento ‘expression’ do object DataColumn resolve de maneira incrível e fácil o tópico:

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