Você pode adicionar uma referência à Microsoft Script Control Library (COM) e usar um código como este para avaliar uma expressão. (Também funciona para JScript.)
Dim sc AsNewMSScriptControl.ScriptControl()
sc.Language="VBScript"Dim expression AsString="1 + 2 * 7"Dim result AsDouble= sc.Eval(expression)
Editar - O ScriptControl é um objeto COM. Na caixa de diálogo "Adicionar referência" do projeto, selecione a guia "COM" e role para baixo até "Microsoft Script Control 1.0" e selecione ok.
houve uma resposta de ma81xx em 15 de novembro de 11
tatigo
1
Você está certo, mas isso não estava usando o método Compute.
Tim Schmelter
Seu exemplo mostra que System.InvalidCastException não foi tratado pelo código de usuário HResult = -2147467262 Como posso corrigir isso?
Yuliia Ashomok
Funciona para mim, você usou este código de exemplo? Use o depurador e inspecione o valor do resultado, o tipo é mencionado.
Tim Schmelter
28
Para qualquer pessoa desenvolvendo em C # no Silverlight, aqui está um truque muito legal que acabei de descobrir que permite a avaliação de uma expressão chamando o mecanismo Javascript:
double result =(double)HtmlPage.Window.Eval("15 + 35");
Eu me pergunto se você poderia fazer referência a isso em outro lugar. Provavelmente não, mas seria legal.
Joel Coehoorn,
4
Como isso avalia o código Javascript arbitrário, você provavelmente deseja limpar sua entrada e certificar-se de que não está exibindo diretamente o resultado. (Eu acho que esta seria uma boa maneira de apresentar o XSS sem perceber)
Dan Esparza
Tente inserir números com um zero à esquerda, o resultado não é confiável. "054 + 6" dá 50, por exemplo.
Terry
9
@djerry, isso ocorre porque os números com zero à esquerda são considerados octais pelo avaliador de JS, e octal 054 é igual ao decimal 44.
É extensível, rápido (por exemplo, tem seu próprio cache) permite que você forneça funções personalizadas e variáveis em tempo de execução manipulando eventos EvaluateFunction / EvaluateParameter. Expressões de exemplo que ele pode analisar:
Ele também lida com Unicode e muitos tipos de dados nativamente. Ele vem com um arquivo antler se você quiser alterar a gramática. Também existe um fork que suporta MEF para carregar novas funções.
Isso é o que eu usei para meu solucionador de equação diferencial, que pegou a entrada de um usuário. A questão está aqui
Kleineg
15
Na verdade, existe um tipo embutido - você pode usar o namespace XPath! Embora exija que você reformate a string para confirmar com a notação XPath. Usei um método como este para lidar com expressões simples:
publicstaticdoubleEvaluate(string expression){var xsltExpression =string.Format("number({0})",newRegex(@"([\+\-\*])").Replace(expression," ${1} ").Replace("/"," div ").Replace("%"," mod "));return(double)newXPathDocument(newStringReader("<r/>")).CreateNavigator().Evaluate(xsltExpression);}
Inicialmente, usei o wrapper c # para muparser . Isso foi muito rápido. A única solução mais rápida que conheço é exprtk . Se você estiver procurando por outras soluções, você pode verificar o benchmark .
Mas no caso do .Net, você pode usar o suporte embutido para compilar o código em tempo de execução. A ideia é ter um arquivo fonte de "modelo" como, por exemplo, recurso embutido onde você pode substituir a fórmula para a avaliação. Em seguida, você passa esse código-fonte da classe preparado para o compilador.
Um modelo básico pode ter a seguinte aparência:
publicclassCSCodeEvaler{publicdoubleEvalCode(){return last =Convert.ToDouble(%formula%);}publicdouble last =0;publicconstdouble pi =Math.PI;publicconstdouble e =Math.E;publicdouble sin(doublevalue){returnMath.Sin(value);}publicdouble cos(doublevalue){returnMath.Cos(value);}publicdouble tan(doublevalue){returnMath.Tan(value);}...
Observe a% formula% onde a expressão será colocada.
Para compilar, use a classe CSharpCodeProvider. Não quero colocar a fonte completa aqui. Mas esta resposta pode ajudar:
Depois de carregar o assembly na memória, você pode criar uma instância de sua classe e chamar EvalCode.
Recentemente, usei o mXparser, que é uma biblioteca de analisador matemático para .NET e JAVA. mXparser suporta fórmulas básicas, bem como fórmulas muito sofisticadas / complicadas (incluindo variáveis, funções, operadores, iteração e recursão).
Expression e =newExpression("1+2*7 + (sin(10) - 2)/3");double v = e.calculate();
Exemplo 2:
Argument x =newArgument("x = 5");Expression e =newExpression("2*x+3", x);double v = e.calculate();
Exemplo 3:
Function f =newFunction("f(x,y) = sin(x) / cos(y)");Expression e =newExpression("f(pi, 2*pi) - 2", f);double v = e.calculate();
Encontrado recentemente - caso você queira experimentar a sintaxe (e veja o caso de uso avançado), você pode baixar o aplicativo Calculadora Escalar que é desenvolvido por mXparser.
Esta é a melhor biblioteca que encontrei. No entanto, ele não suporta nenhum tipo de dados diferente de número! Eu preciso de DateTime e String .. você conhece alguma boa alternativa?
Homam
5
Se você precisa de algo muito simples, pode usar o DataTable:-)
Eu também daria uma olhada no Jace ( https://github.com/pieterderycke/Jace ). Jace é um analisador matemático de alto desempenho e mecanismo de cálculo que oferece suporte a todos os tipos de .NET (.NET 4.x, Windows Phone, Windows Store, ...). Jace também está disponível por meio do NuGet: https://www.nuget.org/packages/Jace
Um analisador matemático simples é muito fácil de construir e requer apenas algumas linhas de código:
Veja este exemplo flexível:
class RPN
{publicstaticdoubleParse(Stack<string> strStk ){if(strStk ==null|| strStk.Count==0){return0;}Stack<double> numStk =newStack<double>();double result =0;Func<double,double> op =null;while(strStk.Count>0){var s = strStk.Pop();switch(s){case"+":
op =( b )=>{return numStk.Pop()+ b;};break;case"-":
op =( b )=>{return numStk.Pop()- b;};break;case"*":
op =( b )=>{return numStk.Pop()* b;};break;case"/":
op =( b )=>{return numStk.Pop()/ b;};break;default:double.TryParse(s,NumberStyles.Any,out result);if(numStk.Count>0){
result = op(result);}
numStk.Push(result);break;}}return result;}}....var str =" 100.5 + 300.5 - 100 * 10 / 100";
str =Regex.Replace(str,@"\s","",RegexOptions.Multiline);Stack<string> strStk =newStack<string>(Regex.Split(str,@"([()*+\/-])",RegexOptions.Multiline).Reverse());
RPN.Parse(strStk);
Para ativar a precedência entre colchetes, uma pilha de pilhas será suficiente, como arquivadas por recursão. Qualquer coisa entre colchetes é colocada em uma nova pilha. Finalmente, você pode oferecer suporte a operações matemáticas de uma forma legível por lambdas.
-1: Basta mesclar isso na resposta @cbp. Há necessidade ZERO de ter duas respostas que são fundamentalmente idênticas quando podemos ter uma resposta fantástica.
Robert MacLean,
1
Implementei um analisador de expressão há alguns anos e publiquei uma versão dele no GitHub e no Nuget: Albatross.Expression recentemente. Ele contém uma classe ExecutionContext que pode avaliar um conjunto de expressões como:
MV = Preço * Qtd;
Preço = (compra + venda) / 2;
Lance = 0,6;
Pergunte = 0,8;
Ele também tem uma verificação de referência circular embutida que é útil para evitar um estouro de pilha.
Você pode usar a biblioteca Math-Expression-Evaluator da qual sou autor. Ele suporta expressões simples, como 2.5+5.9, 17.89-2.47+7.16, 5/2/2+1.5*3+4.58, expressões com parênteses (((9-6/2)*2-4)/2-6-1)/(2+24/(2+4))e expressões com variáveis:
var a =6;var b =4.32m;var c =24.15m;var engine =newExpressionEvaluator();
engine.Evaluate("(((9-a/2)*2-b)/2-a-1)/(2+c/(2+4))",new{ a, b, c});
Você também pode passar parâmetros como variáveis nomeadas:
dynamic dynamicEngine =newExpressionEvaluator();var a =6;var b =4.5m;var c =2.6m;
dynamicEngine.Evaluate("(c+b)*a", a:6, b:4.5, c:2.6);
Suporta .Net Standard 2.0, podendo ser utilizado tanto em projetos .Net Core como em .Net Full Framework e não possui dependências externas.
Dim ec AsNewCiloci.Flee.ExpressionContextDim ex AsIDynamicExpression
ec.Imports.AddType(GetType(Math))
ec.Variables("a")=10
ec.Variables("b")=40
ex = ec.CompileDynamic("a+b")Dim evalData
evalData = ex.Evaluate()Console.WriteLine(evalData)
using System;
using staticMathNet.Symbolics.SymbolicExpression;
using staticSystem.Console;
using staticSystem.Numerics.Complex;
using Complex=System.Numerics.Complex;
namespace MathEvaluator{classProgram{staticreadonlyComplex i =ImaginaryOne;staticvoidMain(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));}}}
Respostas:
Você pode adicionar uma referência à Microsoft Script Control Library (COM) e usar um código como este para avaliar uma expressão. (Também funciona para JScript.)
Editar - versão C #.
Editar - O ScriptControl é um objeto COM. Na caixa de diálogo "Adicionar referência" do projeto, selecione a guia "COM" e role para baixo até "Microsoft Script Control 1.0" e selecione ok.
fonte
Estranho que esta famosa e velha questão não tenha uma resposta que sugira o
DataTable.Compute
"truque" embutido . Aqui está.Os seguintes operadores aritméticos são suportados em expressões:
Mais informações:
DataColumn.Expression
em Expression Syntax .fonte
Para qualquer pessoa desenvolvendo em C # no Silverlight, aqui está um truque muito legal que acabei de descobrir que permite a avaliação de uma expressão chamando o mecanismo Javascript:
fonte
Você já viu http://ncalc.codeplex.com ?
É extensível, rápido (por exemplo, tem seu próprio cache) permite que você forneça funções personalizadas e variáveis em tempo de execução manipulando eventos EvaluateFunction / EvaluateParameter. Expressões de exemplo que ele pode analisar:
Ele também lida com Unicode e muitos tipos de dados nativamente. Ele vem com um arquivo antler se você quiser alterar a gramática. Também existe um fork que suporta MEF para carregar novas funções.
fonte
Na verdade, existe um tipo embutido - você pode usar o namespace XPath! Embora exija que você reformate a string para confirmar com a notação XPath. Usei um método como este para lidar com expressões simples:
fonte
Inicialmente, usei o wrapper c # para muparser . Isso foi muito rápido. A única solução mais rápida que conheço é exprtk . Se você estiver procurando por outras soluções, você pode verificar o benchmark .
Mas no caso do .Net, você pode usar o suporte embutido para compilar o código em tempo de execução. A ideia é ter um arquivo fonte de "modelo" como, por exemplo, recurso embutido onde você pode substituir a fórmula para a avaliação. Em seguida, você passa esse código-fonte da classe preparado para o compilador.
Um modelo básico pode ter a seguinte aparência:
Observe a% formula% onde a expressão será colocada.
Para compilar, use a classe CSharpCodeProvider. Não quero colocar a fonte completa aqui. Mas esta resposta pode ajudar:
Depois de carregar o assembly na memória, você pode criar uma instância de sua classe e chamar EvalCode.
fonte
Mais uma opção agora que Roslyn está disponível:
Você pode usar a biblioteca CodeAnalysis.CSharp.Scripting para isso.
pacotes nuget:
fonte
Recentemente, usei o mXparser, que é uma biblioteca de analisador matemático para .NET e JAVA. mXparser suporta fórmulas básicas, bem como fórmulas muito sofisticadas / complicadas (incluindo variáveis, funções, operadores, iteração e recursão).
https://mxparser.codeplex.com/
https://mathparser.org/
Alguns exemplos de uso:
Exemplo 1:
Exemplo 2:
Exemplo 3:
Encontrado recentemente - caso você queira experimentar a sintaxe (e veja o caso de uso avançado), você pode baixar o aplicativo Calculadora Escalar que é desenvolvido por mXparser.
Cumprimentos
fonte
Se você precisa de algo muito simples, pode usar o
DataTable
:-)fonte
Eu também daria uma olhada no Jace ( https://github.com/pieterderycke/Jace ). Jace é um analisador matemático de alto desempenho e mecanismo de cálculo que oferece suporte a todos os tipos de .NET (.NET 4.x, Windows Phone, Windows Store, ...). Jace também está disponível por meio do NuGet: https://www.nuget.org/packages/Jace
fonte
Um analisador matemático simples é muito fácil de construir e requer apenas algumas linhas de código:
Veja este exemplo flexível:
Para ativar a precedência entre colchetes, uma pilha de pilhas será suficiente, como arquivadas por recursão. Qualquer coisa entre colchetes é colocada em uma nova pilha. Finalmente, você pode oferecer suporte a operações matemáticas de uma forma legível por lambdas.
fonte
100.5 + 300.5 - 100 * 10 / 100 = 30.1
vs391
fonte
Implementei um analisador de expressão há alguns anos e publiquei uma versão dele no GitHub e no Nuget: Albatross.Expression recentemente. Ele contém uma classe ExecutionContext que pode avaliar um conjunto de expressões como:
Ele também tem uma verificação de referência circular embutida que é útil para evitar um estouro de pilha.
fonte
Você pode usar a biblioteca Math-Expression-Evaluator da qual sou autor. Ele suporta expressões simples, como
2.5+5.9
,17.89-2.47+7.16
,5/2/2+1.5*3+4.58
, expressões com parênteses(((9-6/2)*2-4)/2-6-1)/(2+24/(2+4))
e expressões com variáveis:Você também pode passar parâmetros como variáveis nomeadas:
Suporta .Net Standard 2.0, podendo ser utilizado tanto em projetos .Net Core como em .Net Full Framework e não possui dependências externas.
fonte
Flee Fast Lightweight Expression Evaluator
https://flee.codeplex.com
Referência da Língua
Exemplo:
A saída: 50
fonte
MathNet.Symbolics
Não se esqueça de carregar
fonte