实现用户输入算式,其中包含加减乘除,括号以及空格的算式,并且优先计算最里的括号的算式,例如1+ 22*3 2-2 2*(2 3 1+34*33/4+55*(1 2-5 *8+7/ 9)+(20+(39/13+8)+8*4-9)+7 8/9-10*76+(8 6*9))
1、要求不能使用 eval() 的方法
2、字符串的处理
3、正则表达式的使用,re模块
4、递归函数的使用
避免毫无头绪的编写,先从最简单的不包含括号的加减、乘除简单逻辑开始编写,每种编写一个函数,函数里通过字符串的处理以及正则表达式的(re)运用,获取最简单的一个算式。同时通过网上相关资料的查询,并通过自己的理解,实现了部分的改良,以此得到小的进步。
1、实现最小的乘除单元,不包含括号的算式
使用字符串的 split() 方法,将字符串以 * / 分隔成为成为列表,在运用列表的索引提取相关值,并通过 if 、 else的语句判断,使用对应的乘、除法
import re
def multiply_divide(str_number):
'''计算不包含括号的最小乘除单元,用split分隔*/,并计算。'''
ret = float(str_number.split("*")[0]) * float(str_number.split("*")[1]) if "*" in str_number else\
float(str_number.split("/")[0]) / float(str_number.split("/")[1])#使用行内if else语句
return ret
2、使用递归,将不包含括号的最小乘除单元递归运算完
def remove_md(str_number):
'''将不含括号的乘除全部递归算完'''
if "*" not in str_number and "/" not in str_number:
return str_number #没有乘除时递归结束
else:
str_num = re.search(r"-?[\d\.]+[*/]-?[\d\.]+",str_number).group()
#-?[\d\.]+[*/]-?[\d\.]+表示如果*/符号左右数字有负号"-"的都取,例如“-2*-9”形式
str_number = str_number.replace(str_num,"+" + str(multiply_divide(str_num))) \
if len(re.findall(r"-",str_num)) == 2 \
else str_number.replace(str_num, str(multiply_divide(str_num)))
#使用行内if else语句,重点if len(re.findall(r"-",str_num)) == 2,判断是否有俩负号"-","--"乘法为正
return remove_md(str_number) #递归,直到没有乘除
3、实现简单的加减,不包含括号的算式
运用正则表达式 re ,最先将字符串的中相邻是 “ + - ” 的情况,通过相应的替换得到字符串中不存在相邻是 “ + - ” 的情况,然后通过判断首位数字是否为负数并处理合并,最后通过一个循环得到间隔的加减运算符 “ + - ” ,并实现对应的运算。
def add_sub(str_number):
'''计算不包含括号的纯加减运算'''
if re.findall("\+-|-\+|--|\+\+",str_number):
'''检查+-符号相邻的情况,并替换,直到算式里没有+-相邻的情况'''
str_number = str_number.replace(r"+-","-")
str_number = str_number.replace(r"-+", "-")
str_number = str_number.replace(r"--", "+")
str_number = str_number.replace(r"++", "+")
str_list = re.findall("([\d\.]+|\+|-)",str_number)
if str_list[0] == "-":
'''判断第一个是否是负数,同时处理'''
str_list[0] = str_list[0] + str_list[1]
del str_list[1]
sum_num = float(str_list[0])
for i in range(1, len(str_list), 2):
'''循环运算符得出运算符,并按相应计算'''
if str_list[i] == "+":
sum_num += float(str_list[i+1])
else:
sum_num -= float(str_list[i+1])
return sum_num #循环结束,返回运算结果
4、实现不包含括号的思则基本运算
先将字符串的空格去掉,可以运用字符串的 replace() 的方法;然后再通过对 简单加减函数 与 简单乘除递归函数的 调用(嵌套调用)
def basic_opera(str_number):
'''不包含括号的四则运算'''
str_number = str_number.replace(" ","") #去除输入时的多余空白
return add_sub(remove_md(str_number))
5、实现包含括号的字符串的主体运算程序
通过正则表达式 re 的相应匹配,得到最里括号的算式,再通过递归,直到字符串中没有括号()
def main_calcu(str_expre):
'''计算包含括号的表达式字符串str_expre'''
if not re.search(r"\([^()]+\)",str_expre):
return basic_opera(str_expre)
else:
expre = re.search(r"\([^()]+\)",str_expre).group()
str_expre = str_expre.replace(expre,str(basic_opera(expre[1:len(expre)-1])))
return main_calcu(str_expre) #递归,直到不存在括号
6、实现主函数功能
实现字符串的输入,以及将输入的字符串作为参数,进行主体运算函数的调用
def main_func():
'''主程序入口,输入算式,检查是否包含字母,并打印结果'''
str_expre = input("请输入要计算的算式: ")
while True:
if re.findall("[A-Za-z]+",str_expre):
str_expre = input("输入有误,请重新正确输入要计算的算式: ")
else:
# print(main_calcu(str_expre)) #打印计算结果
return main_calcu(str_expre) #返回结果,也中断循环
7、程序的测试
if __name__ == "__main__":
# main_func()
print(main_func())
print(eval("1+22*32-22*(231+34*33/4+55*(12-5*8+7/9)+(20+(39/13+8)+8*4-9)+78/9-10*76+(86*9))"))
'''
print(main_func()): 20704.222222222226
eval计算结果: 20704.222222222226
'''
通过该简单程序的编写,对相应的知识点得到了熟悉与加深,同时也更加清楚自己要多写代码,多看代码,克服眼高手低的问题,争取在编写一个新程序时,更加熟练,思路清晰。
参考资料https://www.cnblogs.com/Wxtrkbc/p/5453349.html