Pergunta

Qual é a melhor foi avaliar uma expressão como o seguinte:
(A e B) ou (A e C) ou (Not B e C)
ou
(A && B) || (A && C) || (! B && C)

No momento da execução, eu estava pensando em converter as expressões acima ao seguinte:
(Verdadeiro e falso) ou (verdadeiro e falso) ou (Não falso e verdadeiro)
ou
(True && False) || (True && False) || (! Falso && True)

Condições: 1) A expressão lógica não é conhecido até a execução. 2) O número variável e os seus valores não são conhecidos até a execução. 3) Os valores de variáveis ??não são nulos.

Eu sei que poderia criar um simples montar com uma classe e um método que eu gerar em tempo de execução com base nas entradas, mas há uma maneira melhor. Eu já fiz isso antes. Use um construtor de string para escrever o código, em seguida, chamar o compilador. Depois disso, você carregar o assembly e chamar o método.

Sugestões?

Graças.

Foi útil?

Solução

Se você estiver usando NET3.5 em seguida, você pode analisar o texto e criar uma árvore sytax abstrata usando as classes de expressão. Em seguida, criar uma instância LambdaExpression adequado e compilá-lo em um delegado, que você pode então executar.

A construção de um construtor de árvore de analisador e sintaxe para esse tipo de bastante simples gramática é bastante um exercício interessante e irá executar um pouco mais rápido do que chamar o compilador (e de mais puro no meu ponto de vista também).

Se você não estiver usando NET3.5, então também não é complicado para implementar uma árvore de sintaxe abstrata si mesmo interpretado.

Outras dicas

Esteja avisado: as duas condições finais que você está falando não são necessariamente equivalentes. Os && operadores em C # irá utilizar evalution curto-circuito, enquanto o operador And lógica em VB não. Se você quer ter certeza das declarações são equivalentes, traduzir um And usuário AndAlso e uma Or usuário OrElse.

Para expresssions simples que você provavelmente não vai notar a diferença. Mas se as condições podem ter efeitos colaterais ou se a diferença de desempenho entre os dois é uma preocupação, isso pode ser importante.

Você pode fazer isso facilmente com:

  1. um gerador de analisador (como ANTLR, mencionado acima) que leva expressões booleanas como entrada e produz uma lista infix e
  2. código para avaliar uma pilha Reverse Polish Notation.

A gramática é algo como isto:

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 avaliar, você fazer isso:

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 símbolos, você tem que substituir o valor de verdade em tempo de execução.

Você pode usar https://github.com/mrazekv/logicalparser

Seu simplesmente biblioteca para escrever expressão lógica (evaulated com mesa precenednce, permite OR, NOT, AND operador e>,> =, <=,

Você pode escrever um simples intérprete / parser. Use algo como ANTLR e reutilização gramáticas existentes.

Se você estiver usando o .NET 3.5, você pode criar uma expressão lambda. Em seguida, você pode criar um delegado dele e chamar como delegado / método padrão. Na internet é um monte de exemplos sobre expressões lambda.

Uma solução seria para montar a expressão como uma string e, em seguida, enviá-lo SQL Server, ou qualquer que seja o seu banco de dados é para avaliação. Substitua as variáveis ??reais com 1 = 1 ou 0 = 1 para verdadeiro e falso, respectivamente, e você iria acabar com uma consulta como esta:

SELECT 1 WHERE (1 = 1 e 0 = 1) ou (1 = 1 e 1 = 1) ou (Não 0 = 1 e 1 = 1)

Então, quando você executar a consulta, você começa a 1 de volta quando o resultado é verdadeiro. Pode não ser a solução mais elegante, mas vai funcionar. Muitas pessoas provavelmente irá aconselhar contra isso, mas eu só vou jogá-lo lá fora, como uma possível solução de qualquer maneira.

Esta não será a melhor resposta, mas eu mesmo tive esse problema há algum tempo.

Aqui está o meu código antigo: VB.Net - nenhuma garantia em tudo

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 uma string com múltiplas '(', ')', 'e', ??'ou' plus 'outras coisas' e quebra a lógica para um booleano, substituindo as coisas com valores booleanos. portanto:

Eu Quaisquer que sejam 'outras coisas' queria avaliar eu tive que colocar em resolveTerm Function () com o comentário "'Funktionen ausführen und zurückgeben, einzelwert!" na página 2. Há a única rightnow avaliação é "Se o número for> 1"

Greetings

Dê uma olhada em minha biblioteca, Proviant . É uma biblioteca .NET padrão usando o Manobras Quintal algoritmo para avaliar expressões booleanas.

Ele também poderia gerar uma tabela de verdade para as suas expressões.

Você também pode implementar sua própria gramática.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top