正则实现基础数学计算器
版本一:
import re s = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )' def atom_calc(exp): """ 计算单个乘除法算术表达式 :param exp: :return: """ if '*' in exp: ret = exp.split("*") return str(float(ret[0])*float(ret[1])) elif '/' in exp: ret = exp.split('/') return str(float(ret[0])/float(ret[1])) def mul_div(exp): """ 计算符合乘除算术表达式 :param exp: :return: """ while True: pattern = '\d+(\.\d+)?[*/]\-?\d+(\.\d+)?' ret = re.search(pattern, exp) if ret: atom_exp = ret.group() ret = atom_calc(atom_exp) exp = exp.replace(atom_exp, ret) else: return exp def format_exp(exp): """ 格式化运算符号 :param exp: :return: """ exp = exp.replace('--', '+') exp = exp.replace('+-', '-') exp = exp.replace('-+', '-') exp = exp.replace('++', '+') return exp def add(exp): """ 计算加减符合算术表达式 :param exp: :return: """ pattern = '[\-]?\d+(?:\.\d+)?' ret = re.findall(pattern, exp) exp = sum(map(lambda x: float(x), ret)) # sum_ = 0 # for i in ret: # sum_ += float(i) # return str(sum_) return str(exp) def calc(exp): """ 计算括号内(不再包含括号的算术表达式)表达式结果 :param exp: :return: """ exp = mul_div(exp) exp = format_exp(exp) exp = add(exp) return exp def main(exp): """ 计算整个算术表达式结果 :param exp: :return: """ exp = exp.replace(' ', '') #去除原始算术表达式中的空格 while True: pattern = '\([^()]+?\)' ret = re.search(pattern, exp) if ret: ret = ret.group() calc_exp = calc(ret) exp = exp.replace(ret, calc_exp) else: break return calc(exp) print(main(s))
版本二:
s = '(1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ))' import re #匹配括号 pattern1 = '\([^\(\)]*\)' #匹配乘除法 pattern2 = r'(?:(?<=[^\d])\-)?\d+(?:\.\d+)?([\*\/])(?:[^\d]?\-)?\d+(?:\.\d+)?' #匹配加减法 pattern3 = r'(?:(?<=[^\d])\-)?\d+(?:\.\d+)?([\+\-])(?:[^\d]?\-)?\d+(?:\.\d+)?' def get_parentheses(pattern, str1): """ #获取最最里层括号内容 :param pattern: #传入pattern1 :param str1: :return: # 返回搜索结果, re.Match.object """ return re.search(pattern, str1) def get_operator(pattern, str2): """ 获取算术表达式 :param pattern:根据情况传入pattern2,pattern3 :param str2: :return: # 返回搜索结果, re.Match.object """ return re.search(pattern, str2) def get_result(ret, pattern): """ 循环处理括号中表达式,得到最后的数字结果返回 :param ret: 括号中的内容 example:(321-321*123/333) :param pattern: 根据情况传入pattern2,pattern3,匹配单个算术表达式 example:1+2,3*4 :return: 括号中算术表达式计算后得到的结果 ret_multiply: 匹配到的单个算术表达式结果, re.Match.object ope: 匹配ret_multiply结果中的算术符, example: +,-,*,/ """ while True: ret_multiply = get_operator(pattern, ret) if ret_multiply: ret_multiply_info = ret_multiply.group() ope = re.search(pattern, ret_multiply_info).group(1) info = ret_multiply_info.split(ope) if ope == "*": result = str(float(info[0]) * float(info[1])) elif ope == "/": result = str(float(info[0]) / float(info[1])) elif ope == "+": result = str(float(info[0]) + float(info[1])) elif ope == "-": result = str(float(info[0]) - float(info[1])) ret = ret.replace(ret_multiply_info, result) else: break return ret def run(info, str_new): """ 接入括号中的算术表达式,然后根据乘除后加减的规则调用get_result进行计算,在计算加减是用替换的方式处理--,+-的情况 :param info: 括号中的内容 example:(321-321*123/333) :param str_new: 原始字符串 :return: 括号表达式计算出来值后,值替换原始字符串中的算术表达式 """ m_result = get_result(info, pattern2) # print("处理乘除法", m_result) m_result = m_result.replace('+-', '-') m_result = m_result.replace('--', '+') minus_result = get_result(m_result, pattern3) # print("处理减法", minus_result) str_new = str_new.replace(info, minus_result.lstrip('(').rstrip(')')) return str_new def calc(str_new): """ 循环匹配括号中的内容,交给run进行处理,括号全部算完之后,算最后一个的算术表达式,得到返回结果。 :param str_new:原始字符串 :return: 最终结果 """ str_new = str_new.replace(' ', "") while True: ret1 = get_parentheses(pattern1, str_new) if ret1: ret1_info = ret1.group() str_new = run(ret1_info, str_new) else: break str_new = run(str_new, str_new) return str_new """ 函数调用关系 calc中调用 get_parentheses获取扩号内容 run根据先乘除后加减的规则,用得到计算结果替换对应的括号表达式 run 中调用 get_result计算加减乘除 get_result 中调用 get_operator 获取单个算是表达式 """ s2 = '(123+9817239*(3--2+4*5/4*3*3-123+321/11*32.1321-1+(321.333-1.321*123.321/333)+123*345/123-(3124+123/321)))' print(eval(s2)) print(calc(s2)) print(eval(s)) print(calc(s))