解题思路
一、计算器运算规则
优先级 匹配格式
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)