实现计算器功能(python)
编译程序时一般都使用后缀表达式进行计算。那什么是后缀表达式呢?
任何一个表达式都可以由操作数、操作符、分解符组成。通常,算数表达式有3中表示:
- 中缀(infix)表示 : <操作数><操作符><操作数>,例如A+B
- 后缀(postfix)表示 : <操作数><操作数><操作符>,例如AB+
- 前缀(prefix)表示 : <操作符><操作数><操作数>,例如+AB
一般利用栈来实现后缀表达式的计算。当遇到操作数时,压栈;当遇到操作符时,弹出两个操作数进行计算,将结果压栈。
实现计算器功能,分两步:
- 中缀表达式变为后缀表达式
- 利用栈进行后缀表达式计算
中缀表达式变为后缀表达式
在进行计算时,要进行优先级的比较。
isp(in stack priority)栈内优先数
icp(in coming priority)栈外优先数
操作符 | # | ( | * / % | + - | ) |
---|---|---|---|---|---|
isp | 0 | 1 | 5 | 3 | 6 |
icp | 0 | 6 | 4 | 2 | 1 |
算法描述:
- 操作符初始,将结束符#入栈,读取字符流s
- 重复步骤,当字符流结束且栈到结束符,停止循环
a. 若s是操作数,直接输出,读取下一个s
b. 若s是操作符,栈顶用op表示:- 若icp(s) > isp(op): s进栈,读取下一个字符
- 若icp(s) < isp(op): 退栈并输出
- 若icp(s) == isp(op): 退栈但不输出,若op == “(”,读取下一个字符
- 算法结束,输出即后缀表达式
代码如下
def infix2postfix(ss):
res = []
stack = ["#"]
isp = {
"+":3,"-":3,"*":5,"/":5,"(":1,")":6,"#":0}
icp = {
"+":2,"-":2,"*":4,"/":4,"(":6,")":1,"#":0}
ss = ss.split()
i = 0
while i < len(ss):
if ss[i].isdigit():
res.append(ss[i])
i += 1
else:
if isp[stack[-1]]<icp[ss[i]]:
stack.append(ss[i])
i += 1
elif isp[stack[-1]]>icp[ss[i]]:
res.append(stack.pop())
else:
stack.pop()
i += 1
while stack[-1] != "#":
res += stack.pop()
return res
利用后缀表达式进行计算
完整代码
def infix2postfix(ss):
res = []
stack = ["#"]
isp = {
"+":3,"-":3,"*":5,"/":5,"(":1,")":6,"#":0}
icp = {
"+":2,"-":2,"*":4,"/":4,"(":6,")":1,"#":0}
ss = ss.split()
i = 0
while i < len(ss):
if ss[i].isdigit():
res.append(ss[i])
i += 1
else:
if isp[stack[-1]]<icp[ss[i]]:
stack.append(ss[i])
i += 1
elif isp[stack[-1]]>icp[ss[i]]:
res.append(stack.pop())
else:
stack.pop()
i += 1
while stack[-1] != "#":
res += stack.pop()
return res
def calculate(ss):
stack = []
for item in ss:
if item.isdigit():
stack.append(int(item))
else:
right = stack.pop()
left = stack.pop()
if item == "+":
ans = left + right
elif item == "-":
ans = left - right
elif item == "*":
ans = left * right
elif item == "/":
ans = left / right
stack.append(ans)
return stack[0]
结果
ss = "9 + 10 / 2 - 4 / ( 6 + 6 )"
ss = infix2postfix(ss)
ans = calculate(ss)
# 13.666666666666666