如何解决计算器表达式计算器-前缀vs后缀表示法?
用于编写自己的计算器(表达式评估器),用于类似以下表达式:
3+2*5
7+(8/2)*5
3*5+8*7
我的印象是,完成此操作的唯一明智的方法是转换为前缀表示法或后缀表示法,然后从那里进行评估。
我前一段时间使用后缀表示法完成了此操作,它似乎工作得很好。当时,我从某个地方(目前不记得在哪里)得到一个想法,即后缀表示法对于这种目的更为标准。我没有尝试使用前缀表示法。
为此任务选择前缀表示法和后缀表示法的优缺点是什么?对于典型的面试问题(例如https://leetcode.com/problems/basic-calculator-ii/),什么是更好的选择?为什么?
P.S。 Python的eval
使用前缀,后缀还是完全不同的方法?我的印象是,这是Python eval
的来源https://github.com/python/cpython/blob/master/Python/ceval.c,但不清楚一般策略是什么。
解决方法
无需先转换为前缀或后缀。如果只评估一次或几次,则可以在解析时进行。我通常这样使用递归下降:
import re
def evalExpr(infixStr):
# precedences for infix operators
precs = {'+':0,'-':0,'/':1,'*':1,'^':2}
# functions of operators
funcs = {
'+': (lambda a,b: a+b),'-': (lambda a,b: a-b),'/': (lambda a,b: a/b),'*': (lambda a,b: a*b),'^': (lambda a,b: a**b)
}
# divide string into tokens
tokens = re.split(r' *([\(\)\+\-\*\^/]) *',infixStr)
tokens = [t for t in tokens if t!='']
# current parse position
pos = 0
# evaluate infix expression at the parse point,# processing only operators above a given precedence
def eval2(minprec,closer=None):
nonlocal pos,tokens
# first we need a number or parenthesized expression
if (pos >= len(tokens)):
raise Exception("Unexpected end")
if (tokens[pos]=="("):
pos += 1
val = eval2(0,")")
pos += 1
else:
val = float(tokens[pos])
pos += 1
# gather operators that consume the value
while pos < len(tokens):
op = tokens[pos]
if op == closer:
return val
prec = precs.get(op)
if prec == None:
raise Exception("operator expected. got " + op)
if prec<minprec: # precedence too low for us
break
pos += 1 # operator OK
# get the argument on the operator's right
# this will go to the end,or stop at an operator
# with precedence <= prec
arg2 = eval2(prec+1,closer)
val = (funcs[op])(val,arg2)
if closer != None:
raise Exception("Expected " + closer)
return val
return eval2(0)
print(evalExpr("5+3*4^2+1")) # prints 54.0
print(evalExpr("7+(8/2)*5")) # prints 27.0
print(evalExpr("3*5+8*7")) # prints 71.0
这种递归下降样式是编写了许多表达式解析器的结果,现在我几乎总是以这种方式解析表达式。它几乎与表达式解析器一样简单,并且可以轻松添加一元运算符和不同类型的括号,以及像赋值运算符一样从右向左关联的运算符。
秘密是eval2
的签名,可以轻松实现优先级规则。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。