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

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

String s = "1 + 2 * 7"; 

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

Вы можете добавить ссылку на библиотеку управления скриптами Microsoft (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) 

Изменить – версия на C #.

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

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

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

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

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

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

Дополнительная информация: DataColumn.Expression в синтаксисе выражений .

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

 double result = (double) HtmlPage.Window.Eval("15 + 35"); 

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

Он расширяемый, быстрый (например, имеет собственный кеш) позволяет вам предоставлять пользовательские функции и переменные во время выполнения, обрабатывая события 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()); 

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

На самом деле есть нечто вроде встроенного – вы можете использовать пространство имен 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("")) .CreateNavigator() .Evaluate(xsltExpression); } 

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

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

Основной шаблон может выглядеть так:

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

Обратите внимание на% -ную формулу%, в которую будет помещено выражение.

Для компиляции используйте class CSharpCodeProvider. Я не хочу включать полный источник здесь. Но этот ответ может помочь:

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

Недавно я использовал 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(); 

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

Еще один вариант теперь, когда Roslyn доступен:

Для этого вы можете использовать библиотеку 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:

       

Если вам нужна очень простая вещь, вы можете использовать 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") 

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

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

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

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

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

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

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

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

Быстрое облегчение оценки expressии

https://flee.codeplex.com

Языковой справочник

  • Арифметические операции Пример: a * 2 + b ^ 2 – 100% 5
  • Пример сравнения: a <> 100
  • AndOrXorNotOperators Пример (логический): a> 100 И не b = 100
  • ShiftOperators Пример: 100 >> 2
  • Пример конкатенации: «abc» + «def»
  • Пример индексирования: arr [i + 1] + 100
  • литералы
  • Пример литья: 100 + cast (obj, int)
  • Пример условного оператора: Если (a> 100 и b> 10, «как больше», «меньше»)
  • InOperator Example (List): If (100 in (100, 200, 300, -1), «in», «not in»)
  • Перегруженные операторы по типам

Пример :

 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

 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("")) .CreateNavigator() .Evaluate(xsltExpression); // ReSharper restore PossibleNullReferenceException } } } 
  • Тип массива - правила для назначения / использования в качестве параметра функции
  • Когда использовать std :: forward для пересылки аргументов?
  • Почему никто не принимает публичные поля в C #?
  • ASP.NET Identity Cookie через поддомены
  • Форматировать десятичное значение для процентных значений?
  • XmlSerializer, дающий FileNotFoundException в конструкторе
  • Открытый оператор new, частный оператор delete: получение C2248 «не может получить доступ к частному пользователю» при использовании нового
  • Нужен многостраничный процесс ASP.NET MVC с обратной связью с пользователем
  • Какой тип указателя я использую, когда?
  • Загрузка файлов не работает - нужна помощь
  • Внедрение Rand
  • Interesting Posts

    Можно ли суммировать весь столбец без установки явных границ ячеек в Excel?

    Может ли FFmpeg использоваться в качестве библиотеки вместо автономной программы?

    Как заставить метод вызвать другой в classах C #?

    как ссылаться на относительный файл из кода и тестов

    Где Skype сохраняет аватары моего контакта в Linux?

    ASP.NET MVC 3 – Partial vs Display Template vs Editor Template

    Реализация шаблона пула объектов C #

    простой HttpURLConnection POST-файл multipart / form-data от android до google blobstore

    Как добраться от сервера MySql до приложения для Android?

    Как запустить процесс как режим администратора в C #

    Как преобразовать целочисленное значение в римскую цифровую строку?

    Теперь жесткие диски дефрагментируют себя?

    Как обнаружить паузу во вводе для UISearchBar / UITextField?

    Получить SSID беспроводной сети, с которой я подключен, с C # .Net в Windows Vista

    java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет VM

    Давайте будем гением компьютера.