Domanda

La cosa migliore era valutare un'espressione come la seguente:
(A e B) Oppure (A e C) Oppure (Non B e C)
O
(A & & B) || (A & & C) || (! B & C)

In fase di esecuzione, stavo pianificando di convertire le espressioni di cui sopra nelle seguenti:
(Vero e falso) Oppure (Vero e falso) Oppure (Non falso e vero)
O
(Vero e falso) || (Vero e falso) || (!Falsa verità)

Condizioni:1) L'espressione logica non è nota fino al runtime.2) La variabile numerica e i relativi valori non sono noti fino al runtime.3) I valori delle variabili non sono mai nulli.

So che potrei creare un semplice assemblaggio con una classe e un metodo che genero in fase di esecuzione in base agli input, ma esiste un modo migliore.L'ho già fatto prima.Utilizza un generatore di stringhe per scrivere il codice, quindi chiama il compilatore.Successivamente, carichi l'assembly e chiami il metodo.

Suggerimenti?

Grazie.

È stato utile?

Soluzione

Se si utilizza .NET3.5, è possibile analizzare il testo e creare un albero di sintassi astratto utilizzando le classi Expression. Quindi creare un'istanza LambdaExpression adatta e compilarla in un delegato, che è quindi possibile eseguire.

Costruire un parser e un generatore di alberi di sintassi per questo tipo di grammatica abbastanza semplice è un esercizio piuttosto interessante, e verrà eseguito un po 'più velocemente di invocare il compilatore (ed è anche più pulito dal mio punto di vista).

Se non si utilizza .NET3.5, non è nemmeno complicato implementare da soli un albero di sintassi astratto interpretato.

Altri suggerimenti

Attenzione: le due condizioni finali di cui stai parlando non sono necessariamente equivalenti. L'amplificatore &; Amp! &; gli operatori in C # useranno la valutazione del corto circuito, mentre l'operatore logico And in VB no. Se vuoi essere sicuro che le dichiarazioni siano equivalenti, traduci un utente AndAlso in Or e un utente OrElse in <=>.

Per espressioni semplici probabilmente non noterai alcuna differenza. Ma se le condizioni possono avere effetti collaterali o se la differenza di prestazioni tra i due è un problema, questo può essere importante.

Puoi farlo facilmente con:

  1. un generatore di parser (come ANTLR, menzionato sopra) che accetta espressioni booleane come input e produce un elenco di infissi e
  2. codice per valutare uno stack di notazione polacca inversa.

La grammatica è simile alla seguente:

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

Per valutare, fai questo:

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

Per i simboli, devi sostituire il valore di verità in fase di esecuzione.

Puoi utilizzare https://github.com/mrazekv/logicalparser

La sua semplice libreria per scrivere espressioni logiche (evocata con tabella precenednce, consente agli operatori OR, NOT, AND e > ;, > =, < =, < su variabili intere e = su variabili stringa)

Puoi scrivere un semplice interprete / parser. Usa qualcosa come ANTLR e riutilizza le grammatiche esistenti.

Se si utilizza .NET 3.5, è possibile creare un'espressione Lambda. Quindi è possibile creare un delegato da esso e chiamare come delegato / metodo standard. Su Internet ci sono molti esempi di Lambda Expressions.

Una soluzione sarebbe quella di assemblare l'espressione come una stringa e quindi inviarlo a SQL Server, o qualunque sia il tuo database per la valutazione. Sostituisci le variabili effettive con 1 = 1 o 0 = 1 rispettivamente per True e False e finiresti con una query come questa:

SELEZIONA 1 DOVE (1 = 1 E 0 = 1) O (1 = 1 E 1 = 1) O (Non 0 = 1 E 1 = 1)

Quindi quando si esegue la query, si ottiene 1 indietro quando il risultato è vero. Potrebbe non essere la soluzione più elegante, ma funzionerà. Molte persone probabilmente lo sconsigliano, ma lo proverò comunque come una possibile soluzione.

Questa non sarà la risposta migliore, ma io stesso ho avuto questo problema qualche tempo fa.

Ecco il mio vecchio codice:VB.Net: nessuna garanzia!

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)

Questo codice mangia una stringa con più "(', ')', "e", "o" più "altre cose" e scompone la logica in un valore booleano sostituendo le cose con valori booleani.Perciò:

Qualunque 'altre cose' volessi valutare, dovevo inserirle nella funzione resolveTerm() al commento "'Funktionen Ausführen und Zurückgeben, Einzelwert!" a pagina 2.Lì l'unica valutazione in questo momento è "Se il numero è > 1"

Saluti

Dai un'occhiata alla mia biblioteca, Proviant . È una libreria .NET Standard che utilizza Algoritmo Shunting Yard per valutare le espressioni booleane.

Potrebbe anche generare una tabella di verità per le tue espressioni.

Potresti anche implementare la tua grammatica.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top