说明
本文是针对符合中缀表达式的式子,才能得出正确的计算结果,这里不讲解中缀表达式.
要计算一个表达式分下面几个步骤:
1: 中缀表达式转成前缀表达式思路如下图:
2:计算前缀表达式
前缀表达式的计算有下面几步:
-
a:从右至左扫描表达式,遇到数字时,将数字压入堆栈.
-
b:遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算并将结果入栈
-
c:重复上述过程,最后栈中就只有一个值,这个值就是计算结果.。
代码
import re
# 自定义堆栈
class Stack:
def __init__(self):
self.items = []
self.index = -1
# def __iter__(self):
# return self
def iter(self):
for i in self.items:
yield i
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
# 获取前缀表达式
def get_pre_exp(str):
num_stact = Stack()
flag_stack = Stack()
exp = re.sub(r"\s+", "", str)
re_exp = exp[::-1] # 反转字符串
for i in re_exp:
if i.isdigit():
num_stact.push(i)
else:
if i in [")", "+", "×", "/", "-", "*"]:
flag_stack.push(i)
if i == "(":
while True:
if ")" not in flag_stack.iter():
raise Exception("表达式括号不匹配")
flag = flag_stack.pop()
if flag == ")":
break
else:
num_stact.push(flag)
while True:
if flag_stack.size() > 0:
f = flag_stack.pop()
num_stact.push(f)
else:
break
return num_stact
# 计算前缀表达式
def caculate(sta):
t = Stack()
for i in sta.iter():
if i.isdigit():
t.push(i)
else:
flag = i
if t.size() >= 2:
left_num = t.pop()
right_num = t.pop()
if flag == "+":
tmp = int(left_num) + int(right_num)
t.push(tmp)
elif flag in ["*", "×"]:
tmp = int(left_num) * int(right_num)
t.push(tmp)
elif flag == "/":
tmp = int(left_num) / int(right_num)
t.push(tmp)
elif flag == "-":
tmp = int(left_num) - int(right_num)
t.push(tmp)
return t.pop()
s = "1 + ((2 + 3) × 4) - 5"
pre_expression = get_pre_exp(s)
print(caculate(pre_expression))