Pergunta

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

  1. Por descendência recursiva
  2. Algoritmo de pátio de malha
  3. Notação polonesa reversa

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

Foi útil?

Solução

Além da resposta de Thomas, é realmente possível acessar as bibliotecas JScript (depreciadas) diretamente de C#, o que significa que você pode usar o equivalente ao JScript's eval função.

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

Outras dicas

Certamente é possível. o CodesNippetComPileUnit A classe faz basicamente isso. Eu escrevi para você algum código de uso de exemplo. Você precisará incluir estes 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 'parâmetros' e 'expressão' por qualquer coisa, e você terá um avaliador de expressão geral.

Se você receber uma FilENotFoundException em resultados.compiledassembly, o snippet falhou em compilar.

Você também pode querer dar uma olhada na classe System.Codedom.Codesnippetexpression. É usado para leitura mais especificamente expressões, mas uma expressão por si só não pode ser compilada, então você precisaria usar mais codificação para criar uma classe trabalhadora e um método em torno dela. Isso é útil se você deseja manipular programaticamente que tipo de classe você está gerando. CodesNippetComPileUnit é bom gerar uma classe trabalhadora inteira de uma só vez (e mais simples para um exemplo), mas para manipulá -la, você precisaria fazer manipulações inconvenientes de string.

Embora o uso de serviços do compilador seja uma solução simples e eficiente, ele levanta sérios problemas de segurança se a expressão for inserida por um usuário, porque poderá executar praticamente nada.

Há outra solução muito simples que é muito mais segura: aproveite o JScript Eval função. Você só precisa seguir estas etapas:

Crie um arquivo JS chamado jsmath.js:

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

Compile -o em uma biblioteca de classes:

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 extremamente bem: Confira aqui , é o analisador de expressão mais flexível que encontrei até agora.

(Usamos para configurar regras de negócios 'legíveis por humanos', com dados fornecidos por um banco de dados do SQL Server)

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

ncalc é o melhor. você pode encontrar isso em codeplex também em pepita.
O NCALC é um avaliador de expressões matemáticas no .NET. O NCALC pode analisar qualquer expressão e avaliar o resultado, incluindo parâmetros estáticos ou dinâmicos e funções personalizadas.

Eu acho que essa é a melhor maneira de todos. Resposta de Peter Repac é incrível. Usando o argumento 'expressão' do objeto Datacolumn resolve incrivelmente e facilmente 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"]);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top