算法要求
输入"任意"算数表达式字符串
例如2+3.1*4-8.2/2,输出计算结果为10.3
但他不能用eval等现成函数完成,还要考虑实现加减乘除
写出该算法需要的知识是
栈,中缀表达式,后缀表达式
栈的特性是先入后出,看参考浏览器的网页的前进和后退(忘记为啥和栈有关系了)
中缀表达式就是平常我们所在书本上处理的表达式,也就是在将符号放在数字之间。
后缀表达式就是将运算符放在运算数之后
算法实现难点
将我们输入的中缀表达式转化为后缀表达式。
本例采用的是空格分隔提取列表中的元素,所以输入数字和符号之间要用空格隔开(其他提取元素的算法暂时未实现)
中缀表达式转后缀表达式
def change_opt(opt):
result = []# list
stack = [] # 栈
item_lists = opt.split(' ') # 以空格为分隔
for item in item_lists: # 取出字符
# 如果当前字符为整数或者小数那么放入结果列表
if item.isdigit() or '.' in item:
result.append(item)
else:
if len(stack) == 0: # 如果栈空,直接入栈
stack.append(item)
# 乘除左括号入栈
elif item in '*/(':
stack.append(item)
elif item == ')': # 右括号出栈
t = stack.pop()
while t != '(': # 此时左括号不为(
result.append(t) # 把右括号入栈
t = stack.pop() # 出栈t
# 符号入栈,进入括号内部
elif item in '+-' and stack[-1] in '*/':
if stack.count('(') == 0:
while stack: # 出栈数字,加入到列表中
result.append(stack.pop())
else: # 碰到左括号,则停止
t = stack.pop()
while t != '(':
result.append(t)
t = stack.pop()
stack.append('(') # 自己加左括号
stack.append(item)
else:
stack.append(item)
# 把栈中数据弹出
while stack:
result.append(stack.pop())
return result
后缀表达式的计算
for循环遍历出后缀表达式中的元素,然后再用if判断提取出元素交给四则运算的函数处理(本例是method函数)
# 后缀表达式计算
def get_value(follow):
num = [] # 定义保存数字的列表
base_opt = ['+','-','*','/']
for i in follow:
if i.isdigit() or '.' in i: # 只含数字或符号.就加入列表,再用float对其处理为浮点型
num.append(float(i)) # 加入保存数字的列表
if i in base_opt: # 判断中缀表达式转化为后缀表达式的字符在定义的符号列表中则输出保存数字的列表
nums2 = num.pop()
nums1 = num.pop()
# 传入函数中进行对应的加减乘除运算
res = method(nums1,nums2,i)
num.append(res)
return num[0] # 提取列表中第一个的值,这个就是输出计算的值,但他如何确保第一个值就是呢,for循环遍历光列表元素
# 处理四则运算的方法;四则运算的本质还是编译器处理,并没有自己用其他方式处理四则运算,
# 这上面后缀表达式只是一种将运算符放在运算数之后
def method(num1,num2,j):
if j == '+':
res = num1 + num2
elif j == '-':
res = num1 - num2
elif j == '*':
res = num1 * num2
else:
res = num1 / num2
return res
完整代码
# -*- coding:utf-8 -*-
# 中缀表达式转换为后缀表达式
# 首先弄这个需要弄清楚什么是中缀表达式,什么是后缀表达式
# 下方就是把中缀表达式转化为后缀表达式
# 本例难点就在于把中缀表达式转化为后缀表达式,本例使用的是空格分隔提取列表中的元素
def change_opt(opt):
result = []# list
stack = [] # 栈
item_lists = opt.split(' ') # 以空格为分隔
for item in item_lists: # 取出字符
# 如果当前字符为整数或者小数那么放入结果列表
if item.isdigit() or '.' in item:
result.append(item)
else:
if len(stack) == 0: # 如果栈空,直接入栈
stack.append(item)
# 乘除左括号入栈
elif item in '*/(':
stack.append(item)
elif item == ')': # 右括号出栈
t = stack.pop()
while t != '(': # 此时左括号不为(
result.append(t) # 把右括号入栈
t = stack.pop() # 出栈t
# 符号入栈,进入括号内部
elif item in '+-' and stack[-1] in '*/':
if stack.count('(') == 0:
while stack: # 出栈数字,加入到列表中
result.append(stack.pop())
else: # 碰到左括号,则停止
t = stack.pop()
while t != '(':
result.append(t)
t = stack.pop()
stack.append('(') # 自己加左括号
stack.append(item)
else:
stack.append(item)
# 把栈中数据弹出
while stack:
result.append(stack.pop())
return result
# 后缀表达式计算
def get_value(follow):
num = [] # 定义保存数字的列表
base_opt = ['+','-','*','/']
for i in follow:
if i.isdigit() or '.' in i: # 只含数字或符号.就加入列表,再用float对其处理为浮点型
num.append(float(i)) # 加入保存数字的列表
if i in base_opt: # 判断中缀表达式转化为后缀表达式的字符在定义的符号列表中则输出保存数字的列表
nums2 = num.pop()
nums1 = num.pop()
# 传入函数中进行对应的加减乘除运算
res = method(nums1,nums2,i)
num.append(res)
return num[0] # 提取列表中第一个的值,这个就是输出计算的值,但他如何确保第一个值就是呢,for循环遍历光列表元素
# 处理四则运算的方法;四则运算的本质还是编译器处理,并没有自己用其他方式处理四则运算,
# 这上面后缀表达式只是一种将运算符放在运算数之后
def method(num1,num2,j):
if j == '+':
res = num1 + num2
elif j == '-':
res = num1 - num2
elif j == '*':
res = num1 * num2
else:
res = num1 / num2
return res
if __name__ == '__main__':
# 输入表达式中的字符需要用空格隔开
opt = input('请输入表达式中的字符用空格隔开:')
result = change_opt(opt)
print(get_value(result))