Est-ce qu'il y a un évaluateur de maths string? in.NET Je ne sais pas.
si j'ai une chaîne avec une expression mathématique valide telle que:
String s = "1 + 2 * 7";
y a-t-il une bibliothèque/fonction intégrée dans .NET qui analysera et évaluera cette expression pour moi et retournera le résultat? Dans ce cas 15.
14 réponses
vous pouvez ajouter une référence à Microsoft Script Control Library (COM) et utiliser du code comme celui-ci pour évaluer une expression. (Fonctionne aussi pour JScript.)
Dim sc As New MSScriptControl.ScriptControl()
sc.Language = "VBScript"
Dim expression As String = "1 + 2 * 7"
Dim result As Double = sc.Eval(expression)
Modifier - version 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 - le ScriptControl est un objet COM. Dans la boîte de dialogue" Ajouter une référence "du projet, sélectionnez L'onglet" COM "et faites défiler vers le bas Jusqu'à" Microsoft Script Control 1.0 " et sélectionnez ok.
étrange que cette question célèbre et ancienne n'a pas une réponse qui suggère le bâtiment DataTable.Compute
-"trick". Elle est ici.
double result = Convert.ToDouble(new DataTable().Compute("1 + 2 * 7", null));
les opérateurs arithmétiques suivants sont supportés par des expressions:
+ (addition)
- (subtraction)
* (multiplication)
/ (division)
% (modulus)
Plus d'informations: DataColumn.Expression
la Syntaxe de l'Expression .
pour quiconque se développe en C# sur Silverlight voici une astuce assez soignée que je viens de découvrir qui permet l'évaluation d'une expression en appelant au moteur Javascript:
double result = (double) HtmlPage.Window.Eval("15 + 35");
avez-vous vu http://ncalc.codeplex.com ?
il est extensible, rapide (par exemple a son propre cache) vous permet de fournir des fonctions et des variables personnalisées au moment de l'exécution en traitant EvaluateFunction/EvaluateParameter events. Exemples d'expressions qu'il peut analyser:
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());
il traite aussi unicode et de nombreux types de données nativement. Il est livré avec un fichier antler si vous voulez changer le grammer. Il y a aussi une fourchette qui prend en charge MEF pour charger de nouvelles fonctions.
en fait il y a une sorte de Construit en un - vous pouvez utiliser L'espace de nom XPath! Bien que cela nécessite que vous reformatiez la chaîne pour confirmer avec la notation XPath. J'ai utilisé une méthode comme celle-ci pour gérer des expressions simples:
public static double Evaluate(string expression)
{
var xsltExpression =
string.Format("number({0})",
new Regex(@"([\+\-\*])").Replace(expression, " ")
.Replace("/", " div ")
.Replace("%", " mod "));
return (double)new XPathDocument
(new StringReader("<r/>"))
.CreateNavigator()
.Evaluate(xsltExpression);
}
J'ai D'abord utilisé l'enveloppe c# pour muparser . Cela a été très rapide. La seule solution plus rapide que je connaisse est exprtk . Si vous cherchez d'autres solutions, vous pouvez consulter le benchmark .
mais dans le cas de .Net vous pouvez utiliser le support builtin pour compiler le code à l'exécution. L'idée est d'avoir un fichier source" modèle " comme par exemple une ressource intégrée où vous pouvez remplacer la formule évaluation. Ensuite, vous passez ce code de classe-source préparé au compilateur.
Un modèle de base pourrait ressembler à ceci:
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); }
...
noter Le %formule% où l'expression sera insérée.
pour compiler utilisez la classe CSharpCodeProvider. Je ne veux pas mettre la source complète ici. Mais cette réponse pourrait aider:
après avoir chargé l'assemblage en mémoire, vous pouvez créez une instance de votre classe et appelez EvalCode.
récemment, j'ai utilisé mXparser, qui est une bibliothèque d'analyseur de mathématiques pour .NET et JAVA. mXparser prend en charge des formules de base ainsi que des formules très sophistiquées / compliquées (variables, fonctions, opérateurs, itération et récursion).
https://mxparser.codeplex.com /
quelques exemples d'usage:
exemple 1:
Expression e = new Expression("1+2*7 + (sin(10) - 2)/3");
double v = e.calculate();
exemple 2:
Argument x = new Argument("x = 5");
Expression e = new Expression("2*x+3", x);
double v = e.calculate();
exemple 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();
meilleures salutations
si vous avez besoin de chose très simple, vous pouvez utiliser le 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")
encore une autre option maintenant que Roslyn est disponible:
vous pouvez utiliser la Codanalyse.CSharp.Bibliothèque de script pour ceci.
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();
}
}
}
colis 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" />
je voudrais aussi jeter un oeil à Jace ( https://github.com/pieterderycke/Jace ). Jace est un analyseur de mathématiques haute performance et un moteur de calcul qui prend en charge toutes les saveurs .NET (.NET 4.x, Windows Phone, Windows Store,...). Jace est également disponible via NuGet: https://www.nuget.org/packages/Jace
un analyseur de mathématiques simple est assez facile à construire, et ne nécessite que quelques lignes de code:
prendre cet exemple flexible:
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);
pour permettre la priorité en mettant entre crochets une pile de piles suffira, comme archivée par récursion. Rien entre les parenthèses est mis sur une nouvelle pile. Enfin, vous pouvez prendre en charge les opérations mathématiques d'une manière lisible par lambdas.
j'ai mis en place un analyseur d'expressions il y a quelques années et en avais publié une version dans GitHub et Nuget:Albatross.Expression récemment. Il contient une classe ExecutionContext qui peut évaluer un ensemble d'expressions telles que:
- MV = Prix * Quantité;
- Prix = (Offre + Demande)/2;
- Bid=.6;
- Ask=.8;
il a également intégré un contrôle de référence circulaire qui est utile pour éviter un débordement de la pile.
fuir Rapide, Léger Évaluateur D'Expression
Référence De Langue
- arithmetic operators exemple: A*2 + b ^ 2-100% 5
- Comparisonopérators exemple: a < > 100
- AndOrXorNotOperators Exemple (logique): > 100 Et Pas b = 100
- ShiftOperators Exemple: 100 >> 2
- exemple de concaténation: "abc" + " def "
- exemple D'indexation: arr[i + 1] + 100
- littérales
- Casting Example: 100 + cast (obj, int)
- ConditionalOperator Exemple: If(a > 100 et b > 10, "à la fois plus", "moins de")
- InOperator Exemple (Liste): Si(100 en (100, 200, 300, -1), "dans", "non")
- Opérateurs Surchargés Sur Types
exemple:
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)
la sortie: 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, " ")
.Replace("/", " div ")
.Replace("%", " mod "));
// ReSharper disable PossibleNullReferenceException
return (double)new XPathDocument
(new StringReader("<r/>"))
.CreateNavigator()
.Evaluate(xsltExpression);
// ReSharper restore PossibleNullReferenceException
}
}
}