2008-12-08 8 views
7

Quel est le meilleur était d'évaluer une expression comme ce qui suit:
(A et B) ou (A et C) ou (non B et C)
ou
(A & & B) || (A & & C) || (! B & & C)
Analyse/expression logique dynamique en C# ou VB?

Lors de l'exécution, je comptais sur la conversion des expressions ci-dessus à ce qui suit:
(vrai et faux) Ou (Vrai et faux) Ou (pas faux et vrai)
ou
(Vrai & & Faux) || (Vrai & & Faux) || (! Faux & & vrai)

Conditions: 1) L'expression logique n'est pas connu avant l'exécution. 2) La variable nombre et leurs valeurs ne sont pas connues avant l'exécution. 3) Les valeurs de variables ne sont jamais nulles.

Je sais que je pourrais créer un assemblage simple avec une classe et une méthode que je génère au moment de l'exécution en fonction des entrées, mais y a-t-il un meilleur moyen. Je l'ai déjà fait. Utilisez un générateur de chaîne pour écrire le code, puis appelez le compilateur. Après cela, vous chargez l'assembly et appelez la méthode.

Suggestions?

Merci.

+0

Qu'est-ce que vous essayez d'accomplir? Pouvez-vous partager comment vous venez aux comparaisons? Cela ressemble à quelque chose qui pourrait être mieux abordé différemment. –

+0

On dirait une liste de choses à comparer. Vous pourriez itérer la liste, et casser quand vous trouvez que deux sont vrais. –

+0

Vous pourriez écrire un analyseur logique propositionnel simple ... Je me souviens d'avoir à faire un pour résoudre le problème de Wumpus World. –

Répondre

7

Si vous utilisez .NET3.5, vous pouvez analyser le texte et créer un arbre de syntaxe abstrait à l'aide des classes Expression. Créez ensuite une instance LambdaExpression appropriée et compilez-la dans un délégué, que vous pouvez ensuite exécuter. Construire un analyseur syntaxique et un arbre de syntaxe pour ce type de grammaire assez simple est un exercice assez intéressant, et s'exécutera plus rapidement que l'invocation du compilateur (et il est plus propre à mon avis).

Si vous n'utilisez pas .NET3.5, il n'est pas compliqué d'implémenter un arbre de syntaxe abstraite interprété.

+3

Pourriez-vous donner un exemple. –

+4

Un lien ou un exemple pourrait être utile. – bernhof

0

Vous pouvez écrire un interpréteur/analyseur simple. Utilisez quelque chose comme ANTLR et réutilisez les grammaires existantes.

4

Soyez averti: les deux dernières conditions dont vous parlez ne sont pas nécessairement équivalentes. Les opérateurs & & en C# utiliseront l'évaluation en court-circuit, contrairement à l'opérateur And logique de VB. Si vous voulez être sûr que les instructions sont équivalentes, traduisez un utilisateur And en AndAlso et un utilisateur Or en OrElse.

Pour des expressions simples, vous ne remarquerez probablement pas de différence. Mais si les conditions peuvent avoir des effets secondaires ou si la différence de performance entre les deux est un problème, cela peut être important.

+0

Qu'ils aient ou non un court-circuit, le résultat de l'expression est le même. La seule différence est que lorsque A, B, C sont des fonctions et des effets de court-circuit, qu'ils soient ou non appelés, cela n'affecte pas le résultat final de l'expression. – Kibbee

+0

@Kibbee - mais cela peut affecter le résultat final du * système * si des effets secondaires sont impliqués. –

0

Si vous utilisez .NET 3.5, vous pouvez créer une expression Lambda. Vous pouvez ensuite en créer un délégué et appeler en tant que délégué/méthode standard. Sur Internet, il y a beaucoup d'échantillons sur les expressions Lambda.

-1

Une solution serait d'assembler l'expression comme une chaîne, puis envoyez-le serveur SQL, ou quel que soit votre base de données pour l'évaluation. Remplacez les variables réelles par 1 = 1 ou 0 = 1 respectivement pour Vrai et Faux, et vous obtiendrez une requête comme ceci:

SELECT 1 OERE (1 = 1 et 0 = 1) Ou (1 = 1 et 1 = 1) ou (Non = 0 1 et 1 = 1)

Ensuite, lorsque vous exécutez la requête, vous obtenez un 1 retour lorsque le résultat est vrai. Peut ne pas être la solution la plus élégante, mais cela fonctionnera. Beaucoup de gens vont probablement déconseiller cela, mais je vais tout de même y jeter un coup d'oeil comme une solution possible.

+6

-1: Ne pas encourager les gens à écrire des hacks comme celui-ci, en particulier dans le code de version. – Juliet

+0

C'est une idée intéressante. Vous pouvez le faire plus facilement en utilisant la version intégrée du serveur SQL, plutôt que de dépendre d'une installation complète. Parfois, des hacks comme celui-ci peuvent sauver votre cul. +1 – Will

3

Vous pouvez le faire facilement avec:

  1. un générateur d'analyseur (comme ANTLR, mentionné ci-dessus) qui prend des expressions booléennes en entrée et produit une liste de infix et
  2. code pour évaluer une pile de notation polonaise inversée .

La grammaire ressemble à ceci:

program: exprList ; 

exprList: expr { Append($1); } 
    | expr OR exprList { Append(OR); } 
    | expr AND exprList { Append(AND); } 
    | NOT exprList { Append(NOT); } 
    | (exprList) { /* Do nothing */ } 
    ; 

expr: var { Append($1); } 
    | TRUE { Append(True); } 
    | FALSE { Append(False); } 
    ; 

Pour évaluer, vous faites ceci:

for each item in list 
    if item is symbol or truth value, push onto RPN stack 
    else if item is AND, push (pop() AND pop()) 
    else if item is OR, push (pop() OR pop()) 
    else if item is NOT, push (NOT pop()) 

result = pop() 

Pour les symboles, vous devez remplacer la valeur de vérité lors de l'exécution.

3

Vous pouvez utiliser https://github.com/mrazekv/logicalparser

Sa simple bibliothèque pour écrire l'expression logique (evaulated avec table precenednce, permet d'OR, NOT, opérateur AND et>,> =, < =, < sur les variables entières et = sur chaîne variables)

0

Ce ne sera pas la meilleure réponse, mais j'ai moi-même eu ce problème il y a quelques temps.

Voici mon ancien code: VB.Net - aucune garantie du tout!

https://cloud.downfight.de/index.php/s/w92i9Qq1Ia216XB

Dim BoolTermParseObjekt As New BoolTermParse 
MsgBox(BoolTermParseObjekt.parseTerm("1 und (((0 oder 1 und (0 oder 4))) oder 2)").ToString) 

Ce code mange une chaîne avec plusieurs « (», «) », « et », « ou » plus « d'autres choses » et se décompose de la logique à un booléen en remplaçant le choses avec des valeurs booléennes. donc:

Quels que soient les « autres choses » Je voulais évaluer je devais mettre en fonction resolveTerm() au commentaire « 'Funktionen ausführen und zurückgeben, Einzelwert! » à la page 2. Il la seule RightNow d'évaluation est « Si le nombre est> 1 »

Salutations