2008-12-08 22 views
7

Cuál es la mejor fue la de evaluar una expresión como la siguiente:
(A y B) o (A y C) o (No B y C)
o
(A & & B) || (A & & C) || (! B & & C)
Análisis/evaluación de expresiones lógicas dinámicas en C# o VB?

En tiempo de ejecución, que estaba planeando convertir las expresiones anteriores a la siguiente:
(verdadero y falso) o (verdadero y falso) o (No es falso y verdadero)
o
(Verdadero & & False) || (Verdadero & & False) || (! Falso & & Verdadero)

Condiciones: 1) La expresión lógica no se conoce hasta tiempo de ejecución. 2) La variable de número y sus valores no se conocen hasta el tiempo de ejecución. 3) Los valores de las variables nunca son nulos.

Sé que podría crear un ensamblaje simple con una clase y un método que genero en tiempo de ejecución basado en las entradas, pero ¿hay una mejor manera. He hecho esto antes. Use un constructor de cadenas para escribir el código, luego llame al compilador. Después de eso, carga el ensamblado y llama al método.

Sugerencias?

Gracias.

+0

¿Qué estás tratando de lograr? ¿Puedes compartir cómo vienes a las comparaciones? Esto parece algo que podría abordarse mejor de manera diferente. –

+0

Parece una lista de cosas para comparar. Podría repetir la lista y romperla cuando encuentre que dos son verdaderas. –

+0

Podrías escribir un analizador sintáctico simple de Propositional ... Recuerdo tener que hacer uno para resolver el problema Wumpus World. –

Respuesta

7

Si usa .NET3.5, puede analizar el texto y crear un árbol de sintaxis abstracto utilizando las clases de expresión. Luego, cree una instancia adecuada de LambdaExpression y compílela en un delegado, que luego podrá ejecutar.

Construir un generador de sintaxis y analizador sintáctico para este tipo de gramática bastante simple es un ejercicio bastante interesante, y se ejecutará un poco más rápido que invocar el compilador (y es más limpio en mi opinión también).

Si no está usando .NET3.5, tampoco es complicado implementar usted mismo un árbol de sintaxis abstracta interpretada.

+3

Podría dar un ejemplo. –

+4

Un enlace o ejemplo podría ser útil. – bernhof

0

Puede escribir un intérprete/analizador simple. Use algo como ANTLR y reutilice las gramáticas existentes.

4

Tenga cuidado: las dos condiciones finales de las que habla no son necesariamente equivalentes. Los operadores & & en C# usarán la evaluación de cortocircuito, mientras que el operador lógico And en VB no lo hará. Si quiere estar seguro de que las declaraciones son equivalentes, traduzca un usuario And a AndAlso y un usuario Or a OrElse.

Para las expresiones simples probablemente no notarás la diferencia. Pero si las condiciones pueden tener efectos secundarios o si la diferencia de rendimiento entre los dos es una preocupación, esto puede ser importante.

+0

Independientemente de si se cortocircuitan o no, el resultado de la expresión es el mismo. La única diferencia es cuando A, B, C son funciones y los efectos de cortocircuito, sean o no llamados, no afecta el resultado final de la expresión. – Kibbee

+0

@Kibbee, pero podría afectar el resultado final del * sistema * si se trata de efectos secundarios. –

0

Si está utilizando .NET 3.5, puede crear una expresión Lambda. Luego puede crear un delegado y llamar como delegado/método estándar. En Internet hay muchas muestras sobre Lambda Expressions.

-1

Una solución sería ensamblar la expresión como una cadena, y luego enviarla a SQL Server, o cualquiera que sea su base de datos para su evaluación. Reemplace las variables reales con 1 = 1 o 0 = 1 para Verdadero y Falso respectivamente, y terminaría con una consulta como esta:

SELECCIONE 1 DÓNDE (1 = 1 Y 0 = 1) O (1 = 1 Y 1 = 1) O (no 0 = 1 y 1 = 1)

Luego, cuando ejecuta la consulta, obtiene un 1 cuando el resultado es verdadero. Puede que no sea la solución más elegante, pero funcionará. Mucha gente probablemente desaconsejará esto, pero de todos modos lo lanzaré como posible solución.

+6

-1: No animes a las personas a escribir hacks como este, especialmente en el código de versión. – Juliet

+0

Es una idea interesante. Puede cambiarlo más fácilmente utilizando la versión incorporada del servidor sql, en lugar de confiar en una instalación completa. A veces los hacks como este pueden salvarle el culo. +1 – Will

3

Esto se puede hacer fácilmente con:

  1. un generador de analizadores sintácticos (como antlr, mencionado anteriormente) que lleva las expresiones booleanas como entrada y produce una lista infija y
  2. código para evaluar una pila notación polaca inversa .

La gramática es como la siguiente:

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

para evaluar, hacer esto:

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

Para los símbolos, que tienen que sustituir el valor de verdad en tiempo de ejecución.

3

Puede utilizar https://github.com/mrazekv/logicalparser

Su simplemente la biblioteca para escribir la expresión lógica (evaulated con mesa precenednce, permite a O, NO, Y operador y>,> =, < =, < en variables enteras y = en la cuerda variables)

0

Esta no será la mejor respuesta, pero yo mismo tuve este problema hace algún tiempo.

Aquí está mi código anterior: VB.Net - ¡sin garantía!

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) 

Este código come una cadena con múltiples '(', ')' 'y' 'o' más 'otras cosas' y se rompe la lógica para un booleano sustituyendo la cosas con valores booleanos. , por lo tanto:

Sean cuales sean 'otras cosas' que querían evaluar que tenía que poner en resolveTerm Función() en el comentario "'Funktionen und ausführen zurückgeben, einzelwert!" en la página 2. No la única rightnow evaluación es "Si el número es> 1"

Saludos