我正在为我的大学课程完成作业,我们需要编写一个脚本来评估一系列用括号括起来的数学表达式(即'(((4) 3)* 2)* 5)')。我们还需要使用堆栈和队列来完成教授为我们提供的这项任务。我让我的代码工作,但它没有给我正确的输出。对我做错的任何见解都很有帮助。
这是我用Python 3编写的代码:
import isfloat
import Queue
import Stack
def expr_eveluate(expr_string):
"""
:Pre: Given a mathematical expression, this function
evaluates it per pairs of brackets.
:Post: The expression must be evaluated per pairs of brackets
:param expr_string: A string of mathematical expressions
:return:
"""
# A queue for data to be processed.
waiting_line = Queue.create()
# A stack where processed operators go.
operator_stack = Stack.create()
# A stack where processed numbers go.
numerical_value = Stack.create()
# Put all the items in Queue
expr = expr_string.split()
for item in expr:
Queue.enqueue(waiting_line, item)
while not Queue.is_empty(waiting_line):
item = Queue.dequeue(waiting_line)
if item == '(':
pass
elif isfloat.isfloat(item):
Stack.push(numerical_value, item)
elif not isfloat.isfloat(item):
Stack.push(operator_stack, item)
else:
num1 = Stack.pop(numerical_value)
num2 = Stack.pop(numerical_value)
op = Stack.pop(operator_stack)
if op == '*':
val = num1 * num2
Stack.push(numerical_value, val)
if op == '/':
val = num1 / num2
Stack.push(numerical_value, val)
if op == '+':
val = num1 + num2
Stack.push(numerical_value, val)
if op == '-':
val = num1 - num2
Stack.push(numerical_value, val)
else:
print("Syntax Error")
return None
return Stack.pop(numerical_value)
答案 0 :(得分:0)
我发现您的代码有几个问题。这是一个破败。
您永远不会将您的数字转换为实际的数字类型。您可能希望在float(item)
案例中将numeric_stack
推送到item
而不只是isfloat.isfloat(item)
。
主if
/ elif
/ else
链中的条件彼此不一致。你可以保留一些相同的逻辑,如果你改变了块的顺序,但我认为如果你改善条件,当前的顺序是好的。
特别是,在行elif not isfloat.isfloat(item):
中,条件将始终为真(因为您已经处理了上一个elif
块中的数字)。这意味着右括号将被推送到运算符堆栈,else
块将永远不会运行。我认为你应该在这里明确地测试预期的运算符,类似于elif item in ("*", "/", "+", "-"):
。
同样,顶级else
块应该是elif item == ")"
,明确测试它希望处理的令牌。
当前if
区块中的else
可能应该是if
和elif
的链,因为您只希望其中一个是一次跑。目前,最后的else
子句将针对任何非-
运算符运行,而不是针对未知运算符值。
说到内部else
块,它应该可以缩进一个级别,以便它是外部if
/ elif
链的一部分而不是内部运算符处理链。您需要检查顶层的无效令牌,因为operator_stack
希望不会再被忽略了。
当您从numeric_stack
中弹出两个数字时,您将按错误的顺序处理它们。从堆栈顶部出来的第一个数字始终是运算符右侧的值,而弹出的第二个数字将是左侧的值。目前,您将3 / 4
解释为4 / 3
。只需在您进行num1
调用的行中交换num2
和pop
,即可轻松解决此问题。您甚至可以考虑重新命名这些变量,例如right
和left
,以便更清楚地了解操作的完成方式。
这个问题与您的代码不是一个问题,但是您已经显示了示例输入。如果您在'( ( (4 / 3) * 2) * 5)'
上运行代码,由于括号紧紧包裹,它将无法正确处理。您需要将'( ( ( 4 / 3 ) * 2 ) * 5 )'
传递给它,因此您正在使用的split
调用将正确地分隔所有令牌。我会检查你的任务细节,看你是否需要编写更复杂的标记器,或者你是否可以更加小心你用于测试的输入。