如何使用逻辑运算符评估前缀表达式
Posted
技术标签:
【中文标题】如何使用逻辑运算符评估前缀表达式【英文标题】:how to evaluate prefix expression for with logical operator 【发布时间】:2018-01-18 06:45:25 【问题描述】:我有一个带有多个 AND 和 OR 运算符的前缀表达式,创建了超过 1 的级别,我编写的算法在单个深度上工作正常,但在深度超过 1 时搞砸了结果。我正在使用 python
前缀列表:-['OR', 'AND', '=', ['.', 'grade'], 12, '>=', ['.', 'gpa'], ['.', '$', 'GPA'], 'AND', '=', ['.', 'a'], ['.', 'b'], '>', ['.', 'c'], ['.', 'd']]
def prefix_evaluation(prefix_list):
opstack = []
operand_stk = []
pending_opd = False
for token in prefix_list:
if token in operators:
opstack.append(token)
pending_opd = False
else:
operand = token
if pending_opd:
while len(operand_stk) > 0:
opd_1 = operand_stk.pop()
operator = opstack.pop()
operand = [operator, opd_1, operand]
operand_stk.append(operand)
pending_opd = True
return operand_stk.pop()
预期结果:
[ OR,
[ AND,
[ AND,
[ '=', ['.', 'grade'], 12],
[ '>=', ['.', 'gpa'], ['.', '$', 'GPA']]
]
[ AND,
['=', ['.', 'a'], ['.', 'b']],
['>', ['.', 'c'], ['.', 'd']]
]
]
]
实际结果:
['OR',
['AND',
['AND',
['=', ['.', 'grade'], 12],
['>=', ['.', 'gpa'],
['.', '$', 'GPA']]],
['=', ['.', 'a'], ['.', 'b']]],
['>', ['.', 'c'], ['.', 'd']]]
【问题讨论】:
抛开一切,查找递归下降表达式解析或 Dijkstra Shunting-yard 算法。 【参考方案1】:为了使列表更具可读性,我将12
、['.', 'grade']
、['.', 'c']
等所有操作数都替换为n
。另外,我已经用=
替换了所有算术运算符,例如'>='
、'>'
。
现在您的列表看起来像 OR AND = n n = n n AND = n n = n n
我使用圆括号、方括号和大括号来强调这些术语如何组合在一起——或者应该组合在一起
(= n n)
实际上是一个由一个运算符和两个操作数组成的列表,如['>=', 12, 12]
显示预期结果与实际结果之间差异的图形透视图如下:
当程序解析子列表 OR AND = n n = n n
时,它将形成操作数 [AND (= n n) (= n n)]
(以及仍在操作符堆栈中的额外 OR
)。如您所见,此操作数对预期结果和实际结果都是通用的。
当程序解析子列表OR AND = n n = n n AND = n n
(注意额外的AND = n n
)时,它将具有已经形成的[AND (= n n) (= n n)]
操作数,以及新的操作数AND
和操作数(=n n)
.它将分组为 AND [AND (= n n) (= n n)] (= n n)
。这就是程序的作用,它的编写方式。现在真的有办法告诉你的程序:嘿,需要形成第二个[AND (= n n) (= n n)]
,然后才将两者与OR
连接起来。
打个比方,这就像期望一个逐字符读取的解析器意识到 1+2*3 不是 (1+2)*3,而是 1+(2*3),除非您以某种方式指定乘法优先于加法。
这里的陷阱是您将算术和逻辑运算符放在同一个篮子里。难怪它们在构建表达式时具有相同的优先级(priority)。
更好的方法是区分算术表达式,例如
(= n n)
和像 [AND E1 E2]
这样的逻辑表达式,通过将它们放在两个不同的堆栈中,以及像 n
这样的基本操作数的第三个堆栈。还将算术运算符(如=
)与逻辑运算符(如AND
)放在不同的堆栈中。并且只有现在你可以强加规则 'AND' 运算符应该只链接两个算术或两个逻辑表达式,而不是一个算术与一个逻辑表达式,以避免你当前的输出并获得预计一个。
但我觉得堆栈方法很麻烦,最好按照某人的建议使用递归。
【讨论】:
以上是关于如何使用逻辑运算符评估前缀表达式的主要内容,如果未能解决你的问题,请参考以下文章