需求——开发一个简单的Python计算器
1.实现加减乘除以及括号优先级解析
2.用户输入3+5*((80-40+(-40/8)*(9-2*9/3-5/3*98/4*2998+10*568/14))-(-4*6)/(27-3*8))等类似公式后,必须自己解析出里面的各种符号(不得调用eval等偷懒),运算后得出结果,结果要正确。总程序
1 import re 2 #一、对公式进行简单处理(去掉空格及公式化简) 3 def format_string(string): 4 string = string.replace(' ','') 5 string = string.replace('++','+') 6 string = string.replace('+-','-') 7 string = string.replace('-+','-') 8 string = string.replace('--','+') 9 string = string.replace('*+','*')10 string = string.replace('/+','/')11 return string12 #二、对于不符合要求的公式进行异常处理,给出错误提示信息13 def check_expression(string):14 check_result = True15 if not string.count("(") == string.count(")"):16 print('括号不对称')17 check_result = False18 if re.findall('[a-z]',string.lower()):19 print('表达式有错,包含非法字符')20 check_result = False21 return check_result22 #三、进行乘除运算,并将计算的结果替换掉原公式中的乘除法运算23 def mul_div(string):24 #正则表达式匹配(匹配乘除)25 regular = '\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*'26 #一直到公式中没有除法或乘法运算时,退出循环27 while re.findall(regular,string):#注意:乘除法可以没有顺序28 expression = re.search(regular,string).group()29 # 计算乘法,并将计算的结果替换原来的式子30 if expression.count('*'):31 x,y=expression.split('*')32 mul_result=str(float(x)*float(y))33 string=string.replace(expression,mul_result)34 string=format_string(string)35 # 计算除法,并将计算的结果替换原来的式子36 elif expression.count('/'):37 x, y = expression.split('/')38 div_result = str(float(x) / float(y))39 string = string.replace(expression, div_result)40 string = format_string(string)41 return string42 #四、进行加减法运算43 def add_sub(string):44 add_regu = '[\-]?\d+\.?\d*\+[\-]?\d+\.?\d*'45 sub_regu = '[\-]?\d+\.?\d*\-[\-]?\d+\.?\d*'46 # 计算加法,注意:加减法也可以没有顺序47 while re.findall(add_regu,string):48 add_list=re.findall(add_regu,string)49 for add_str in add_list:50 x, y = add_str.split("+")51 add_result = str(float(x) + float(y))52 string = string.replace(add_str, add_result)53 string = format_string(string)54 while re.findall(sub_regu, string):55 sub_list = re.findall(sub_regu, string)56 for sub_str in sub_list:57 numbers = sub_str.split('-')58 # 计算开头为(-a-b)这种情况59 if len(numbers) == 3:60 result = 061 for v in numbers:62 if v:63 result -= float(v)64 else:65 x = numbers[0]66 y = numbers[-1]67 sub_result = float(x) - float(y)68 string = string.replace(sub_str,str(sub_result))69 string = format_string(string)70 return string71 #五、主逻辑程序72 info=True73 while info:74 source = input("请输入要计算的公式:")75 if check_expression(source):76 strs = format_string(source)77 while source.count('(') > 0:78 # 匹配最里层括号的内容79 strs = re.search('\([^()]*\)', source).group()#在这里^是不包含的意思,[^()]+就是不包含括号的所有字符——返回最里面的括号80 replace_str = mul_div(strs)81 replace_str = add_sub(replace_str)82 # 每次计算的结果去掉括号83 source = format_string(source.replace(strs, replace_str[1:-1]))84 # else下边的逻辑是计算不带括号的式子85 else:86 replace_str = mul_div(source)87 replace_str = add_sub(replace_str)88 source = source.replace(source, replace_str)89 print(source)90 signal=input("是否继续?y/n")91 if signal=='y':92 info=True93 elif signal=='n':94 info=False95 print("已退出,欢迎下次使用!")
难点
1.匹配最里层括号的正则表达式:'\([^()]*\)'
2.匹配乘除法及加减法的正则表达式:
乘除——'\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*'
加——'[\-]?\d+\.?\d*\+[\-]?\d+\.?\d*'
减——'[\-]?\d+\.?\d*\-[\-]?\d+\.?\d*'
3.主逻辑的设计
自我总结
此项目为借助已有代码所写;
相比基本语法,代码整体的逻辑设计更重要;
函数的思想还没有完全掌握;
代码的流程逻辑还需要提升;
其实代码也是模块化的,一个模块想清楚了,其他的也相似。
继续努力!
2019年5月7日