欢迎来到Louis的博客

人生三从境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
扩大
缩小

正则实现基础数学计算器

版本一:

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+23*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))

 

posted on 2018-08-23 14:59  Louiszj  阅读(505)  评论(0编辑  收藏  举报

导航