简单版计算器
解题思路
一、计算器运算规则
优先级 匹配格式
1. 小括号(最底层的) 括号里没有括号
小括号里算式计算优先级:
2.幂运算 (正数)**(正数)、(正数)**(负数) ---支持小数
3.乘除 (正数或负数)(*/)(正数或负数) ---支持小数
4.加减 (正数或负数)(+-)(正数或负数) ---支持小数
二、运算流程
1.search匹配第一个最底层的括号
2.通过match对象的groups方法获取括号里算式
3.对括号内的算式进行幂运算匹配
4.调用幂运算函数对匹配到的对象进行处理
5.用sub将结果替换括号内算式的匹配到的对象
6.重复3、4、5,直到没有匹配对象
7.对替换的算式进行乘除运算匹配
8.调用乘除运算函数对匹配到的对象进行处理
9.用sub将结果替换括号内算式的匹配到的对象
10.重复7、8、9直到没有匹配对象
11.对替换的算式进行加减运算匹配
12.调用加减运算函数对匹配到的对象进行处理
13.用sub将结果替换括号内算式的匹配到的对象
14.重复11、12、13直到没有匹配对象
15、重复上述步骤,直到没有括号
16.得到没有括号的算式后,只要再按照幂、乘除、加减步骤走
17.得到结果
流程图
我还发现python在处理运算时,会自动帮我们处理正负号,所以在匹配时不用太多的去关心数字前的正负号
代码实现
#题目:求得字符串里'1-2*((60-30+9*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'计算式的结果 import re #匹配规则 brackets = re.compile('\(([^()]+)\)') powers = re.compile('(\d+\.?\d*)\*\*(\-?\d+\.?\d*)') mul_div = re.compile('(\-?\d+\.?\d*)([*/])(\-?\d+\.?\d*)') add_cut = re.compile('(\-?\d+\.?\d*)([+\-])(\-?\d+\.?\d*)') def powers_calculate(match_obj): ''' 处理幂运算 :param match_obj: 需要处理的match对象 :return:算式的结果 ''' mat_grs = match_obj.groups() n1 = float(mat_grs[0]) n2 = float(mat_grs[1]) return n1**n2 def mul_div_calculate(match_obj): ''' 处理乘除运算 :param match_obj: 需要处理的match对象 :return: 算式的结果 ''' mat_grs = match_obj.groups() n1 = float(mat_grs[0]) n2 = float(mat_grs[2]) if mat_grs[1] == '*': return n1*n2 else: return n1/n2 def add_cut_calculate(match_obj): ''' 处理加减运算 :param match_obj: 需要处理的match对象 :return: 算式的结果 ''' mat_grs = match_obj.groups() n1 = float(mat_grs[0]) n2 = float(mat_grs[2]) if mat_grs[1] == '+': return n1+n2 else: return n1-n2 #数据源 data_sour = '1-2*((60-30+9*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))' # data_sour = input('请输入你要计算的算式:') #================================================================================== #匹配最底层的括号 brackets_match = brackets.search(data_sour) #对匹配到的括号进行处理 while True: if brackets_match: #判断匹配成功与否 print(brackets_match.group()) #(9-2*5/3+7/3*99/4*2998+10*568/14) mat_groups1 = brackets_match.groups() #得到去括号的组的值,不过此时这里是元组 print(mat_groups1) #('9-2*5/3+7/3*99/4*2998+10*568/14',) #处理幂运算 text = mat_groups1[0] #得到最底层括号里的算式字符串 powers_match = powers.search(text) #匹配幂运算 while True: if powers_match: #判断匹配成功与否 print(powers_match.group()) ret1 = powers_calculate(powers_match) #调用幂运算函数 print(ret1) text = re.sub(powers,str(ret1),text,1) #把得到的幂运算结果替换匹配到的字符串 powers_match = powers.search(text) #对替换的字符串再次进行幂运算匹配 else: break #匹配失败,就退出匹配幂运算的循环 #处理乘除运算 mul_div_match = mul_div.search(text) #对处理幂运算后的字符串进行乘除运算匹配 while True: if mul_div_match: #判断匹配成功与否 print(mul_div_match.group()) ret2 = mul_div_calculate(mul_div_match) #调用乘除运算函数 print(ret2) text = re.sub(mul_div,str(ret2),text,1) #把得到的乘除运算结果替换匹配的字符串 print(text) mul_div_match = mul_div.search(text) #对处理后的字符串再进行乘除运算匹配 else: break #匹配失败,就退出匹配乘除运算的循环 #处理加减运算 add_cut_match = add_cut.search(text) #对处理乘除后的字符串进行加减运算匹配 while True: if add_cut_match: #判断匹配成功与否 print(add_cut_match.group()) ret3 = add_cut_calculate(add_cut_match) #调用加减运算函数 text = re.sub(add_cut,str(ret3),text,1) #用得到的加减运算结果替换匹配的字符串 print(text) add_cut_match = add_cut.search(text) #对处理后的字符串再进行加减运算匹配 else: break #匹配失败,退出匹配加减运算的循环 data_sour = re.sub(brackets,text,data_sour,1) #把括号里的计算结果替换匹配的括号 brackets_match = brackets.search(data_sour) #再次对处理后字符串进行括号的匹配 else: break #匹配不到括号,就退出匹配括号的循环 #对处理括号完后的算式进行最后的运算 #幂 powers_match = powers.search(data_sour) while True: if powers_match: ret1 = powers_calculate(powers_match) data_sour = re.sub(powers,str(ret1),data_sour,1) powers_match = powers.search(data_sour) else: break #乘除 mul_div_match = mul_div.search(data_sour) while True: if mul_div_match: ret1 = mul_div_calculate(mul_div_match) data_sour = re.sub(mul_div, str(ret1), data_sour, 1) mul_div_match = mul_div.search(data_sour) else: break #加减 add_cut_match = add_cut.search(data_sour) while True: if add_cut_match: ret1 = add_cut_calculate(add_cut_match) data_sour = re.sub(add_cut, str(ret1), data_sour, 1) add_cut_match = add_cut.search(data_sour) else: break print('最后结果为:',data_sour) #验证结果 data_sour = '1-2*((60-30+9*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))' jieguo = eval(data_sour) print('验证结果:',jieguo)