Есть строка математика оценщик в .NET?

голоса
70

Если у меня есть строка с действительным математическим выражением, такие как:

String s = 1 + 2 * 7;

Есть встроенный в библиотеке / функция в .NET, которая будет анализировать и оценивать, что выражение для меня и вернуть результат? В этом случае 15.

Задан 10/12/2008 в 05:14
источник пользователем
На других языках...                            


15 ответов

голоса
54

Странно , что этот известный и старый вопрос не имеет ответа , который предполагает предопределённые DataTable.Compute- «трюк». Вот.

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

Следующие арифметические операторы поддерживаются в выражениях:

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

Дополнительные сведения: DataColumn.Expressionв Expression Syntax .

Ответил 14/09/2013 в 00:05
источник пользователем

голоса
48

Вы можете добавить ссылку на Microsoft Script Library Control (COM) и использовать такой код, чтобы оценить выражение. (Также работает для JScript.)

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

Edit - C # версии.

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

Edit - The ScriptControl является COM объект. В диалоговом окне «Добавить ссылку» проекта выберите вкладку «COM» и прокрутите вниз до «Управление Microsoft Script 1.0» и выберите ОК.

Ответил 25/12/2008 в 00:48
источник пользователем

голоса
28

Ни для кого развивается в C # на Silverlight здесь довольно ловкий трюк, который я только что обнаружил, что позволяет оценить выражение, вызвав к двигателю Javascript:

double result = (double) HtmlPage.Window.Eval("15 + 35");
Ответил 25/12/2008 в 00:37
источник пользователем

голоса
21

Вы видели http://ncalc.codeplex.com ?

Это расширяемый, быстрый (например, имеет свой собственный кэш) позволяет предоставлять пользовательские функции и varaibles во время выполнения обработки событий EvaluateFunction / EvaluateParameter. Пример выражения можно разобрать:

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

Он также обрабатывает юникода и многие тип данных изначально. Он поставляется с файлом пантов, если вы хотите изменить грамматику. Существует также вилка, которая поддерживает MEF для загрузки новых функций.

Ответил 09/12/2010 в 10:35
источник пользователем

голоса
15

На самом деле есть своего рода встроенный в одном - вы можете использовать пространство имен XPath! Несмотря на то, что требует, чтобы вы переформатировать строки, чтобы подтвердить с XPath нотации. Я использовал метод, как это обрабатывать простые выражения:

    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);
    }
Ответил 04/02/2010 в 01:59
источник пользователем

голоса
11

Первоначально я использовал C # обертки для muparser . Это было очень быстро. Единственное решение , которое я быстрее знаю exprtk . Если вы ищете другие решения , которые вы можете извлечь тест .

Но в случае .Net можно использовать встроенную поддержку для компиляции кода во время выполнения. Идея заключается в том, чтобы иметь «шаблон» исходный файл, как, например, внедренный ресурс, где вы можете заменить формулу для оценки. Затем вы проходите этот подготовленный класс-исходный код для компилятора.

Основной шаблон может выглядеть следующим образом:

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); }
    ...

Обратите внимание на% формуле% где выражение будет введено в.

Для того, чтобы скомпилировать использовать класс CSharpCodeProvider. Я не хочу , чтобы положить в полном источнике здесь. Но этот ответ может помочь:

После того, как у вас есть в памяти сборка загружена Вы можете создать экземпляр вашего класса и вызвать EvalCode.

Ответил 19/01/2016 в 06:35
источник пользователем

голоса
7

Недавно я использовал mXparser, который является математический анализатор библиотеки для .NET и JAVA. mXparser поддерживает основные формулы, а также очень орнаментальные / сложные из них (в том числе переменные, функции, операторы, итерации и рекурсии).

https://mxparser.codeplex.com/

http://mathparser.org/

Несколько примеров:

Пример 1:

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

Пример 2:

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

Пример 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();

С наилучшими пожеланиями

Ответил 03/03/2016 в 23:22
источник пользователем

голоса
5

Еще один вариант теперь Рослины доступны:

Вы можете использовать библиотеку CodeAnalysis.CSharp.Scripting для этого.

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

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" />
Ответил 22/03/2016 в 13:53
источник пользователем

голоса
3

Простой математический анализатор довольно легко построить, и требует лишь несколько строк кода:

Возьмите этот гибкий пример:

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

Чтобы включить приоритет, заключая стек стеков будет достаточно, например, как архивированные рекурсией. Все, что в скобках ставится на новый стек. Наконец, вы можете поддерживать математические операции в чистой доступной форме с помощью лямбды.

Ответил 21/07/2016 в 05:20
источник пользователем

голоса
3

Я также хотел бы посмотреть на Джейсе ( https://github.com/pieterderycke/Jace ). Джейс является высокой производительностью по математике анализатора и расчет двигатель , который поддерживает все .NET ароматизаторы (.NET 4.x, Windows Phone, Windows Store, ...). Джейс также доступен через NuGet: https://www.nuget.org/packages/Jace

Ответил 27/01/2014 в 10:13
источник пользователем

голоса
3

Если вам нужна очень простая вещь , которую вы можете использовать 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")
Ответил 15/11/2011 в 11:28
источник пользователем

голоса
0

MathNet.Symbolics

using System;
using static MathNet.Symbolics.SymbolicExpression;
using static System.Console;
using static System.Numerics.Complex;
using Complex = System.Numerics.Complex;

namespace MathEvaluator
{
    class Program
    {
        static readonly Complex i = ImaginaryOne;

        static void Main(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));
        }
    }
}

Не забудьте загрузить

<PackageReference Include="MathNet.Symbolics" Version="0.20.0" />
Ответил 07/03/2019 в 18:51
источник пользователем

голоса
0

Бегите Fast Lightweight Expression Evaluator

https://flee.codeplex.com

Справочник по языку

  • ArithmeticOperators Пример: а * 2 + B ^ 2 - 100% 5
  • ComparisonOperators Пример: <> 100
  • Пример AndOrXorNotOperators (логическое): а> 100 И Нет Ь = 100
  • ShiftOperators Пример: 100 >> 2
  • Конкатенация Пример: "ABC" + "DEF"
  • Индексирование Пример: обр [+ 1] + 100
  • литералы
  • Литье Пример: 100 + литье (OBJ, Int)
  • ConditionalOperator Пример: Если (а> 100 и б> 10, "и больше", "меньше")
  • InOperator Пример (список): Если (100 в (100, 200, 300, -1), "в", "не")
  • Перегруженные Операторы по типам

Пример :

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)

Выход: 50

Ответил 18/07/2015 в 09:57
источник пользователем

голоса
0

Я реализовал выражение парсер несколько лет назад и опубликовал версию этого в GitHub и NuGet: Albatross.Expression недавно. Он содержит класс ExecutionContext , который может оценить набор выражений , таких как:

  • MV = Цена * Кол-во;
  • Цена = (Bid + Ask) / 2;
  • Bid = 0,6;
  • Ask = 0,8;

Он также имеет встроенный в круговой контрольной проверки, которая является полезной, чтобы избежать переполнения стека.

Ответил 15/06/2015 в 14:32
источник пользователем

голоса
-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
        }

    }
}
Ответил 13/02/2013 в 18:28
источник пользователем

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