Existe uma matemática avaliador cadeia no .NET?

votos
70

Se eu tiver uma string com uma expressão matemática válido, como:

String s = 1 + 2 * 7;

Existe um construído em biblioteca / função em .NET que irá analisar e avaliar essa expressão para mim e retornar o resultado? Neste caso 15.

Publicado 10/12/2008 em 05:14
fonte usuário
Em outras línguas...                            


14 respostas

votos
54

Estranho que esta questão famoso e antigo não tem uma resposta que sugere a builtin DataTable.Compute- "truque". Aqui está.

double result = Convert.ToDouble(new DataTable().Compute("1 + 2 * 7", null));

Os seguintes operadores aritméticos são suportados em expressões:

+ (addition)
- (subtraction)
* (multiplication)
/ (division)
% (modulus)

Mais informações: DataColumn.Expressionno Expression Syntax .

Respondeu 14/09/2013 em 00:05
fonte usuário

votos
48

Você pode adicionar uma referência à Biblioteca de Controle Script Microsoft (COM) e usar um código como este para avaliar uma expressão. (Também funciona para JScript.)

Dim sc As New MSScriptControl.ScriptControl()
sc.Language = "VBScript"
Dim expression As String = "1 + 2 * 7"
Dim result As Double = sc.Eval(expression)

Editar - C version #.

MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControl();
sc.Language = "VBScript";
string expression = "1 + 2 * 7";
object result = sc.Eval(expression);            
MessageBox.Show(result.ToString());

Editar - O ScriptControl é um objeto COM. No "Adicionar referência" de diálogo do projeto, selecione a guia "COM" e desça até "Microsoft Script Control 1.0" e selecione ok.

Respondeu 25/12/2008 em 00:48
fonte usuário

votos
28

Para qualquer pessoa em desenvolvimento em C # no Silverlight aqui é um truque bastante elegante que eu só descobri que permite a avaliação de uma expressão chamando para o motor de Javascript:

double result = (double) HtmlPage.Window.Eval("15 + 35");
Respondeu 25/12/2008 em 00:37
fonte usuário

votos
21

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 varaibles em tempo de execução por manipulação de eventos EvaluateFunction / EvaluateParameter. Exemplo expressões ele pode analisar:

Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)"); 

  e.Parameters["Pi2"] = new Expression("Pi * Pi"); 
  e.Parameters["X"] = 10; 

  e.EvaluateParameter += delegate(string name, ParameterArgs args) 
    { 
      if (name == "Pi") 
      args.Result = 3.14; 
    }; 

  Debug.Assert(117.07 == e.Evaluate()); 

Ele também lida com unicode & muitos tipo de dados nativamente. Ele vem com um arquivo de chifre se você quiser mudar a gramática. Há também uma bifurcação que suporta MEF para carregar novas funções.

Respondeu 09/12/2010 em 10:35
fonte usuário

votos
15

Na verdade não é uma espécie de um construído em um - você pode usar o namespace XPath! Embora exija que você reformatar a corda para confirmar com a notação XPath. Eu usei um método como este para lidar com expressões simples:

    public static double Evaluate(string expression)
    {
        var xsltExpression = 
            string.Format("number({0})", 
                new Regex(@"([\+\-\*])").Replace(expression, " ${1} ")
                                        .Replace("/", " div ")
                                        .Replace("%", " mod "));

        return (double)new XPathDocument
            (new StringReader("<r/>"))
                .CreateNavigator()
                .Evaluate(xsltExpression);
    }
Respondeu 04/02/2010 em 01:59
fonte usuário

votos
11

Inicialmente eu usei o c # wrapper para muparser . Isso foi muito rápido. A solução só é mais rápido que eu sei é exprtk . Se você está à procura de outras soluções que você pode fazer o checkout da referência .

Mas no caso de .Net você pode usar o suporte nativo para compilar o código em tempo de execução. A idéia é ter um arquivo de origem "template" como recurso por exemplo incorporado, onde pode substituir a fórmula para a avaliação. Então você passa esta classe-código-fonte preparado para o compilador.

Um modelo básico poderia ser assim:

public class CSCodeEvaler
{
    public double EvalCode()
    {
        return last = Convert.ToDouble(%formula%);
    }

    public double last = 0;
    public const double pi = Math.PI;
    public const double e = Math.E;
    public double sin(double value) { return Math.Sin(value); }
    public double cos(double value) { return Math.Cos(value); }
    public double tan(double value) { return Math.Tan(value); }
    ...

Observe a fórmula%%, onde a expressão vai ser colocado em.

Para compilar usar o CSharpCodeProvider classe. Eu não quero colocar na fonte completa aqui. Mas esta resposta pode ajudar:

Depois de ter o assembly na memória carregado você pode criar uma instância de sua classe e chamar EvalCode.

Respondeu 19/01/2016 em 06:35
fonte usuário

votos
7

Recentemente eu estava usando mXparser, que é uma biblioteca de analisador de matemática para .NET e JAVA. mXparser suporta fórmulas básicas, bem como / as complicadas muito extravagantes (incluindo variáveis, funções, operadores, iteração e recursão).

https://mxparser.codeplex.com/

http://mathparser.org/

Alguns exemplos de utilização:

Exemplo 1:

Expression e = new Expression("1+2*7 + (sin(10) - 2)/3");
double v = e.calculate();

Exemplo 2:

Argument x = new Argument("x = 5");
Expression e = new Expression("2*x+3", x);
double v = e.calculate();

Exemplo 3:

Function f = new Function("f(x,y) = sin(x) / cos(y)");
Expression e = new Expression("f(pi, 2*pi) - 2", f);
double v = e.calculate();

Cumprimentos

Respondeu 03/03/2016 em 23:22
fonte usuário

votos
5

Outra opção agora que Roslyn está disponível:

Você pode usar a biblioteca CodeAnalysis.CSharp.Scripting para isso.

using Microsoft.CodeAnalysis.CSharp.Scripting;
using System;

namespace ExpressionParser
{
    class Program
    {
        static void Main(string[] args)
        {
            //Demonstrate evaluating C# code
            var result = CSharpScript.EvaluateAsync("System.DateTime.Now.AddDays(-1) > System.DateTime.Now").Result;
            Console.WriteLine(result.ToString());

            //Demonstrate evaluating simple expressions
            var result2 = CSharpScript.EvaluateAsync(" 5 * 7").Result;
            Console.WriteLine(result2);
            Console.ReadKey();
        }
    }
}

pacotes NuGet:

<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Common" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.CSharp.Scripting" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Scripting" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Scripting.Common" version="1.1.1" targetFramework="net461" />
Respondeu 22/03/2016 em 13:53
fonte usuário

votos
3

Um analisador de matemática simples é bastante fácil de construir, e requer apenas algumas linhas de código:

Veja este exemplo flexível:

class RPN
{
    public static double Parse( Stack<string> strStk )
    {
        if (strStk == null || strStk.Count == 0 )
        {
            return 0;
        }
        Stack<double> numStk = new Stack<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 = new Stack<string>(
     Regex.Split(str, @"([()*+\/-])", RegexOptions.Multiline).Reverse()
);
RPN.Parse(strStk);

Para habilitar precedência por Bracketing de uma pilha de pilhas será suficiente, tais como arquivados por recursão. Qualquer coisa entre parênteses é colocada em uma nova pilha. Finalmente, você pode apoiar as operações de matemática de uma forma legível limpa por lambdas.

Respondeu 21/07/2016 em 05:20
fonte usuário

votos
3

Eu também ter um olhar para Jace ( https://github.com/pieterderycke/Jace ). Jace é um analisador de matemática de alto desempenho e mecanismo de cálculo que suporta todos os sabores NET (.NET 4.x, Windows Phone, o Windows Store, ...). Jace também está disponível através NuGet: https://www.nuget.org/packages/Jace

Respondeu 27/01/2014 em 10:13
fonte usuário

votos
3

Se você precisar de algo muito simples que você pode usar o DataTable:-)

Dim dt As New DataTable
dt.Columns.Add("A", GetType(Integer))
dt.Columns.Add("B", GetType(Integer))
dt.Columns.Add("C", GetType(Integer))
dt.Rows.Add(New Object() {12, 13, DBNull.Value})

Dim boolResult As Boolean = dt.Select("A>B-2").Length > 0

dt.Columns.Add("result", GetType(Integer), "A+B*2+ISNULL(C,0)")
Dim valResult As Object = dt.Rows(0)("result")
Respondeu 15/11/2011 em 11:28
fonte usuário

votos
0

Fuja rápido avaliador Expressão Lightweight

https://flee.codeplex.com

Referência da linguagem

  • Exemplo ArithmeticOperators: a * 2 + b ^ 2 - 100% 5
  • ComparisonOperators Exemplo: a <> 100
  • Exemplo AndOrXorNotOperators (lógico): a> 100 E Não b = 100
  • ShiftOperators Exemplo: 100 >> 2
  • Concatenação Exemplo: "abc" + "def"
  • Exemplo indexação: arr [I + 1] + 100
  • literais
  • Exemplo fundição: 100 + fundido (obj, int)
  • ConditionalOperator Exemplo: se (a> 100 e b> 10 "tanto maior", "inferior")
  • Exemplo InOperator (List): Se (100 em (100, 200, 300, -1) "em", "não em")
  • Operadores sobrecarregados em tipos

exemplo:

Imports Ciloci.Flee
Imports Ciloci.Flee.CalcEngine
Imports System.Math

    Dim ec As New Ciloci.Flee.ExpressionContext
    Dim ex As IDynamicExpression
    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)

A saída: 50

Respondeu 18/07/2015 em 09:57
fonte usuário

votos
0

I implementado um analisador de expressão há alguns anos e tinha publicado uma versão dele no GitHub e Nuget: Albatross.Expression recentemente. Ele contém uma classe ExecutionContext que pode avaliar um conjunto de expressões, tais como:

  • MV = Preço * Qtd;
  • Preço = (Lance + Ask) / 2;
  • Bid = 0,6;
  • Pergunte = 0,8;

Também foi construído na verificação de referência circular que é útil para evitar um excesso de pilha.

Respondeu 15/06/2015 em 14:32
fonte usuário

votos
-1
namespace CalcExp
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            double res = Evaluate("4+5/2-1");

            Console.WriteLine(res);

        }

        public static double Evaluate(string expression)
        {
            var xsltExpression =
                string.Format("number({0})",
                    new Regex(@"([\+\-\*])").Replace(expression, " ${1} ")
                                            .Replace("/", " div ")
                                            .Replace("%", " mod "));

// ReSharper disable PossibleNullReferenceException
            return (double)new XPathDocument
                (new StringReader("<r/>"))
                    .CreateNavigator()
                    .Evaluate(xsltExpression);
// ReSharper restore PossibleNullReferenceException
        }

    }
}
Respondeu 13/02/2013 em 18:28
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more