# stack implement expression evaluation
priority = {'(': -1, ')': -1, '-': 0, '+': 0, '/': 1, '*': 1}
operator_map = {'+': lambda x, y: x + y, '-': lambda x, y: x - y, '/': lambda x, y: x / y, '*': lambda x, y: x * y}
operators = priority.keys()
def _exp(opr, opd, current_level, pop=False):
"""计算, 将前面优先级高的表达式先计算出来, 或将括号中的值计算出来,或最后运算所有的表达式
current_level 为当前遍历运算符优先级, 前一个运算符优先级小与当前优先级, 表示所有计算已完成,则停止计算
pop 表示是否将符号列表中的'('pop, 如果当前字符是')',则pop为True
"""
while len(opd) >= 2:
o = opr.pop() # 运算子
if o == '(':
if not pop:
opr.append(o)
break
if priority[o] < current_level:
opr.append(o)
break
a = opd.pop() # 运算数
b = opd.pop()
opd.append(operator_map[o](b, a))
def exp(s):
opr = [] # 运算符集
opd = [] # 运算子集
levels = [-1] # 记录当前优先级,每遇到一个括号,则增加一个优先级记录
flag = False # 正数累积,flag=False表示一个数字的开头
for c in s:
if c in operators:
if c == '(':
opr.append(c)
levels.append(-1)
continue
if c == ')':
_exp(opr, opd, -1, True)
levels.pop()
continue
level = levels[-1]
if level == -1 and c == '-': # 开头-号, 填0, 增加level, 先算, 如果负号前有数字,则continue后,flag还是True,
opr.append(c)
opd.append(0)
levels[-1] = float('inf')
continue
current_level = priority[c]
if level >= current_level:
_exp(opr, opd, current_level)
levels[-1] = current_level
opr.append(c)
flag = False
else:
if flag:
v = opd.pop() * 10 + int(c)
opd.append(v)
# print(opd, opr, levels)
continue
opd.append(int(c))
flag = True
if len(levels) != 1: # 括号没封口
raise TypeError('valid expression')
_exp(opr, opd, -1) # 最后计算
if len(opr) != 0: # 计算完,运算子集应为空
raise TypeError('valid expression')
return opd[-1]
if __name__ == '__main__':
# s = input('>>>')
# print(exp(s))
ss = ['100-(-30+15)*5', '-1234-23+4*5-6', '-1*2/2-2+3']
for s in ss:
print(s, '=', exp(s), '........', eval(s))
python练习(14)——使用栈实现eval函数的部分功能(加减乘除,括号运算, 负号)
最新推荐文章于 2023-10-25 11:53:01 发布