正则表达式实现计算器
# __author: busensei # data: 2018/8/15 from functools import reduce import re def cal_atomexp(atom_exp): # 计算乘除法 if '*' in atom_exp: a, b = atom_exp.split('*') atom_res = float(a) * float(b) elif '/' in atom_exp: a, b = atom_exp.split('/') atom_res = float(a) / float(b) return str(atom_res) def cal_muldiv(inner_bracket): while True: # 计算括号里的所有乘除法 # 匹配第一个乘除法 inner_bracket = (9-2*5/3+7/3*99/4*2998+10*568/14) ret = re.search('\d+(\.\d+)?[*/]-?\d+(\.\d+)?', inner_bracket) if not ret: break atom_exp = ret.group() # 获取乘除法表达式 # 2*5 atom_res = cal_atomexp(atom_exp) # 计算乘除法的函数,得到结果 10.0 inner_bracket = inner_bracket.replace(atom_exp, str(atom_res)) # inner_bracket = (9-10.0/3+7/3*99/4*2998+10*568/14) # 将得到的结果与匹配到的表达式进行兑换 return inner_bracket # 返回的是一个纯加减法组成的算式 def cal_addsub(inner_bracket): # 计算括号中的所有加减法 # (9 - 3.3333333333333335 + 173134.50000000003 + 405.7142857142857) ret_l = re.findall('[-+]?\d+(?:\.\d+)?', inner_bracket) return str(reduce(lambda a, b: float(a) + float(b), ret_l)) def format_exp(exp): # 给表达式做格式化 exp = exp.replace('--', '+') exp = exp.replace('+-', '-') exp = exp.replace('++', '+') exp = exp.replace('-+', '-') return exp def main(s): s = s.replace(' ', '') while True: # 找最内层的小括号 inner_bracket = re.search('\([^()]+\)', s) if not inner_bracket: break # 找不到小括号了就退出 inner_bracket = inner_bracket.group() inner_bracket_bak = inner_bracket inner_bracket = cal_muldiv(inner_bracket) # 括号内的 : 计算了所有乘除法,只剩下加减法的表达式 inner_bracket = format_exp(inner_bracket) res = cal_addsub(inner_bracket) s = s.replace(inner_bracket_bak, res) s = cal_muldiv(s) s = format_exp(s) s = cal_addsub(s) return s # s = '1-2*((60-30 +(9-2*5/3+7/3*99/4*2998+10*568/14)*(-40 / 5))-(-4*3)/(16-3*2))' s = input('>>>') print(main(s)) print(eval(s))
''' 计算流程: 1.将括号表达式(内部不包含括号)匹配出来 2.计算括号表达式的值,用计算值替换原括号表达式 计算处理流程: 1)从左至右匹配,匹配出乘法或除法表达式,计算出值,塞回去替换匹配的内容 2)乘除法运算都已处理完,对剩下表达式从左至右匹配 3)匹配一个加法或减法运算式,计算出值,塞回去,替换匹配的表达式 4)直到没有匹配运算式,停止,本轮括号表达式计算替换值流程完成 3.再次进行括号表达式(内部不包含括号)匹配 4.重复2 5.直到匹配不出括号表达式,直接对剩余运算式进行乘除加减处理 ''' import re p1 = re.compile(r'\+\s*?-|-\s*?\+') # 匹配'+-或-+' 匹配-+是为了处理用户输入原始表达式中有-+的情况 p2 = re.compile(r'-\s*?-') # 匹配'--' def process_multi_divis(s): pattern = re.compile(r'-?\d+(?:\.?\d+)?\s*?[*/]{1}\s*?-?\s*?\d+(?:\.?\d+)?') # 匹配 *,/,*-,/- 四种情况 while 1: result_process_p1 = re.sub(p1, '-', s) s = re.sub(p2, '+', result_process_p1) r = re.search(pattern, s) if r: r = r.group() if '*' in r: a, b = r.split('*') result = float(a.strip()) * float(b.strip().replace(' ', '')) # 5 *- 6这种表达式,去除负号与数字之间空格 elif '/' in r: a, b = r.split('/') result = float(a.strip()) / float(b.strip().replace(' ', '')) s = s.replace(r, str(result)) else: return s def process_plus_reduce(s): pattern = re.compile(r'-?\d+(?:\.?\d+)?\s*?[+-]{1}\s*?\d+(?:\.?\d+)?') while 1: result_process_p1 = re.sub(p1, '-', s) s = re.sub(p2, '+', result_process_p1) r = re.search(pattern, s) if r: r = r.group() if '+' in r: a, b = r.split('+') result = float(a.strip()) + float(b.strip()) elif '-' in r: if r.startswith('-'): # 处理类似 -5-10 这种表达式 nums = r.split('-') a, b = nums[1], nums[2] result = - float(a.strip()) - float(b.strip()) else: a, b = r.split('-') result = float(a.strip()) - float(b.strip()) s = s.replace(r, str(result), 1) # 只替换一次,避免遇到1+1+1+1这样的表达式,发生多次替换的情况 else: return s def process_parentheses(s): pattern = re.compile(r'\([^(]+?\)') # 匹配最内层括号 while 1: r = re.findall(pattern, s) if r: for item in r: expression = item[1:-1] # 去掉首尾括号 r1 = process_multi_divis(expression) # 处理乘除法 r2 = process_plus_reduce(r1) # 处理加减法 s = s.replace(item, r2) # 处理完成,替换计算结果后,表达式中可能会存在'+-','--'这种运算符,需匹配进行替换; '+-'替换为'-','--'替换为'+' result_process_p1 = re.sub(p1, '-', s) s = re.sub(p2, '+', result_process_p1) else: return s def main(): expression = input('请输入要计算的表达式:') result_step1 = process_parentheses(expression) # 处理括号 result_step2 = process_multi_divis(result_step1) # 计算乘除法 final_result = process_plus_reduce(result_step2) # 计算加减法 print('计算结果:', final_result) if __name__ == '__main__': while 1: main()