我需要制作一个程序,接受数学表达式的用户输入(expr(,并处理找到答案的问题。但是,我们不允许使用eval((函数。赋值指出,我们应该假设用户将输入的运算符只有:+、-、*、/、%。操作数也被假定为一位整数。
我的想法是将操作数转换为整数,并列出所有可以使用的运算符。然后,使用if语句查看操作符如何匹配我的列表。
到目前为止,我能够想出这些代码行:
operand1 = expr[1]
operator = expr[2]
operand2 = expr[3]
operators = ['+','-','*','/','%']
我这样做是为了索引输入表达式中每个操作数和运算符的位置。我被困在这里,希望有人能帮助我如何前进。代码的结果需要输出用户输入的表达式以及表达式的结果。如果表达式的第二个操作数是0,并且运算符是除法,则代码输出"None"。
您可以使用ast.parse
解析表达式。
>>> import ast
>>> expr = ast.parse("3 + 5", mode="eval")
然后您可以分析生成的解析树。在这个特定的实例中,您关心表达式的主体。
>>> expr
<_ast.Expression object at 0x10992c438>
>>> expr.body
<_ast.BinOp object at 0x10a926320>
该对象具有感兴趣的属性:left
、op
和right
。你会看到操作员
>>> expr.body.op
<_ast.Add object at 0x10a91a208>
以决定如何处理操作数。
>>> expr.body.left.n + expr.body.right.n
8
因此,一个可以处理乘法和加法的简单递归函数可能看起来像
def evaluate_expr(expr):
if isinstance(expr, ast.Expression):
return evaluate_expr(expr.body)
elif isinstance(expr, ast.Num):
return expr.n
elif isinstance(expr, ast.BinOp):
op = expr.op
left = evaluate_expr(expr.left)
right = evaluate_expr(expr.right)
if isinstance(op, ast.Add):
return left + right
elif isinstance(op, ast.Mult):
return left * right
raise ValueError(f"Can't evaluate {expr}")
e = ast.parse("3 + 5 * 2", mode="eval")
print(evaluate_expr(e.body)) # Outputs 13
请参阅ast
模块的文档,了解树中可以出现哪些其他节点,以便您可以调整evaluate_expr
来处理其他操作、括号等。ast.dump
对于探索如何解析表达式也很有用。
>>> ast.dump(e, annotate_fields=False)
'Expression(BinOp(Num(3), Add(), BinOp(Num(5), Mult(), Num(2))))'
这清楚地表明解析器处理优先级:3 + 5 * 2
不是结果乘以2的3 + 5
,而是3
加上5 * 2
的结果(较低的节点具有较高的优先级,因为树是从下往上计算的(。
这假设您的输入实际上是一个有效的Python表达式。如果没有,您将需要编写自己的解析器,但一旦您有了解析树,对该树的评估将以类似的方式进行(尽管树的节点是您在解析中创建的任何节点,而不一定是ast.Bin
等人由ast.parse
创建的节点(。
如果此输入字符串中只有一个运算符(例如5 + 9
(,则首先列出要计算的所有运算符operators = ["+", "-", "*", "/", "%"]
然后你必须遍历这个列表中的每个运算符,如果它在字符串中,则继续
# I'm defining the string here manually but you can do it with input()
expression_string = "5 + 9"
for i in range(0, len(operators)):
if operators[i] in expression_string:
....
如果操作符在expression_string中,则首先必须将其拆分为两个操作数,并在浮动中转换这两个操作
operands = expression_string.split(operators[i])
# Converting the two numbers into floats
operands[0] = float(operands[0])
operands[1] = float(operands[1])
现在,最后一步是通过if循环遍历您想要计算的每个运算符并进行计算
if operators[i] == "+":
result = operands[0] + operands[1]
elif operators[i] == "-":
result = operands[0] - operands[1]
elif operators[i] == "*":
result = operands[0] * operands[1]
elif operators[i] == "/":
result = operands[0] / operands[1]
elif operators[i] == "%":
result = operands[0] % operands[1]
现在,这个字符串的结果存储在变量"中;结果";
我希望这能帮助你
EDIT:您只需在最后一个if循环下写入print(result)
即可打印结果。也可以在循环elif operators[i] == "/"
中检查操作数是否为0,然后将result
保存为None