Question

Il existe de nombreux algorithmes d'évaluation d'expressions, par exemple:

  1. Par descente récursive
  2. Algorithme de parc de triage
  3. Notation polonaise inversée

Existe-t-il un moyen d'évaluer une expression mathématique à l'aide de la réflexion C # .net ou d'une autre technologie .net moderne?

Était-ce utile?

La solution

Pour compléter la réponse de Thomas, il est en fait possible d'accéder aux bibliothèques JScript (obsolètes) directement à partir de C #, ce qui signifie que vous pouvez utiliser l'équivalent de la fonction eval de JScript.

using Microsoft.JScript;        // needs a reference to Microsoft.JScript.dll
using Microsoft.JScript.Vsa;    // needs a reference to Microsoft.Vsa.dll

// ...

string expr = "7 + (5 * 4)";
Console.WriteLine(JScriptEval(expr));    // displays 27

// ...

public static double JScriptEval(string expr)
{
    // error checking etc removed for brevity
    return double.Parse(Eval.JScriptEvaluate(expr, _engine).ToString());
}

private static readonly VsaEngine _engine = VsaEngine.CreateEngine();

Autres conseils

C'est certainement possible. La classe CodeSnippetCompileUnit fait essentiellement cela. Je vous ai écrit un exemple de code d'utilisation. Vous devrez inclure ces espaces de noms:

  • System.CodeDom.Compiler;
  • System.CodeDom;
  • Microsoft.CSharp;
  • System.Reflection;

Voici le code:

string source = @"
class MyType
{
    public static int Evaluate(<!parameters!>)
    {
        return <!expression!>;
    }
}
";

string parameters = "int a, int b, int c";
string expression = "a + b * c";

string finalSource = source.Replace("<!parameters!>", parameters).Replace("<!expression!>", expression);

CodeSnippetCompileUnit compileUnit = new CodeSnippetCompileUnit(finalSource);
CodeDomProvider provider = new CSharpCodeProvider();

CompilerParameters parameters = new CompilerParameters();

CompilerResults results = provider.CompileAssemblyFromDom(parameters, compileUnit);

Type type = results.CompiledAssembly.GetType("MyType");
MethodInfo method = type.GetMethod("Evaluate");

// The first parameter is the instance to invoke the method on. Because our Evaluate method is static, we pass null.
int result = (int)method.Invoke(null, new object[] { 4, -3, 2 });

Remplacez 'paramètres' et 'expression' par quoi que ce soit, et vous aurez vous-même un évaluateur d'expression générale.

Si vous obtenez une exception FileNotFoundException dans results.CompiledAssembly, l'extrait de code n'a pas pu être compilé.

Vous pouvez également consulter la classe System.CodeDom.CodeSnippetExpression. Il est utilisé plus spécifiquement pour la lecture d'expressions, mais une expression en elle-même ne peut pas être compilée. Vous devez donc utiliser plus de CodeDom pour créer une classe de travail et une méthode autour. Ceci est utile si vous voulez pouvoir manipuler par programme le type de classe que vous générez. CodeSnippetCompileUnit est bien de générer une classe de travail entière à la fois (et plus simple pour un exemple), mais pour la manipuler, vous auriez à faire des manipulations de chaîne peu pratiques.

Bien que l’utilisation des services du compilateur soit une solution simple et efficace, elle pose de graves problèmes de sécurité si l’expression est saisie par un utilisateur, car il pourrait exécuter n'importe quoi .

.

Il existe une autre solution très simple et beaucoup plus sécurisée: tirez parti de la fonction JScript Eval . Il vous suffit de suivre ces étapes:

Créez un fichier js nommé JsMath.js:

class JsMath
{
    static function Eval(expression : String) : double
    {
        return eval(expression);
    };
}

Compilez-le dans une bibliothèque de classe:

jsc /t:library JsMath.js

Référencez la bibliothèque JsMath dans votre projet C # et utilisez-la comme ceci:

double result = JsMath.Eval(expression);

Pour moi, Vici.Parser fonctionne extrêmement bien: regardez-le ici , c'est l'analyseur d'expression le plus flexible que j'ai trouvé jusqu'à présent.

(nous l'avons utilisé pour configurer des règles métier "lisibles par l'homme", avec des données fournies par une base de données de serveur SQL)

Des exemples sont disponibles et le développeur fournit un très bon support (consultez le forum du site Web).

ncalc est le meilleur. vous pouvez le trouver dans codeplex également dans un nugget.
NCalc est un évaluateur d'expressions mathématiques en .NET. NCalc peut analyser n'importe quelle expression et évaluer le résultat, y compris les paramètres statiques ou dynamiques et les fonctions personnalisées.

Je pense que c'est la meilleure façon de tout. La réponse de Petar Repac est étonnante. L'utilisation de l'argument 'expression' de l'objet DataColumn résout facilement et incroyablement le sujet:

static double Evaluate(string expression)
{
    var loDataTable = new DataTable();
    var loDataColumn = new DataColumn("Eval", typeof(double), expression);
    loDataTable.Columns.Add(loDataColumn);
    loDataTable.Rows.Add(0);
    return (double)(loDataTable.Rows[0]["Eval"]);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top