女神讲解大作业 -- re正则计算器程序 超级注释版

import re
def mul_div(exp):
    '''
    计算最简单的两个数之间的乘除法
    :param exp: str数据类型的 两个数的乘除法表达式,例如'2.34*3.21'
    :return: str数据类型的计算结果
    '''

                                        #来自def cal_no_bracket(no_bracket_exp):  # 计算没有括号的
    if '*' in exp:                      #如果是乘法算式 No.11
        a,b = exp.split('*')            #把算式两边数字提取出 No.12
        return str(float(a)*float(b))   #进行运算 把值返回给调用本函数的函数 No.13
    else:
        a, b = exp.split('/')           #除法算式 把两边数字提取出 No.14
        return str(float(a) / float(b)) #进行运算 把值返回给调用本函数的函数 No.15

def format_exp(exp):
    '''
    完成表达式格式整理,将一些叠在一起的符号整理成一个符号
    :param exp: str数据类型的表达式 '1.23++3+-4--5'
    :return: 整理之后的str数据类型的字符串,'1.23+3-4+5'
    '''

    #来自def cal_no_bracket(no_bracket_exp):    no_bracket_exp = format_exp(no_bracket_exp)
 # 计算没有括号的

    exp = exp.replace('++','+')#修正符号 No.25-28
    exp = exp.replace('-+','-')
    exp = exp.replace('+-','-')
    exp = exp.replace('--','+')
    return exp      #返回的是正常的计算式子 No.29

def cal_no_bracket(no_bracket_exp):  #计算没有括号的
    '''
    计算内部不再有其他小括号的表达式
    :param no_bracket_exp:字符串数据类型的,内部不再含有其他小括号的表达式,例如:(9-2*5/3+7/3*99/4*2998+10*568/14)
    :return: float数据类型的结果
    '''
    # 再计算乘除法
    while True:
        mul_dic_exp = re.search('\d+(\.\d+)?[*/]-?\d+(\.\d+)?', no_bracket_exp)#循环匹配出最小括号里的乘法或除法式子 No.7
        if mul_dic_exp:                      #如果式子里还有乘法或除法 No.8
            md_exp = mul_dic_exp.group()     #把乘除法式子提取出来 No.9
            res = mul_div(md_exp)            #把式子送走进行计算 No.10 return回来的res是乘数法算式计算后的值 No.16
            no_bracket_exp = no_bracket_exp.replace(md_exp, res)    #把乘除法运算的值替换到原式子里 No.17
        else:break
    # 表达式中的符号管理,把++ 编程+ ,--变成+
    #来自def calculator(exp),此时传进来的exp已经没有乘除号,所以直接进入这行代码:
    no_bracket_exp = format_exp(no_bracket_exp)  #将没有乘除法的式子送走修正符号 No.24 返回的是符号正常的计算式子 No.30 
    # 再计算加减法
    res_lst = re.findall('[-+]?\d+(?:\.\d+)?',no_bracket_exp)#从没有乘除法的符号正常的式子里匹配出所有带正负号的数字,findall装入列表 No.31
    sum_n = 0               #计数 No.32 
    for i in res_lst:       #遍历列表 No.33
        sum_n += float(i)   #每个数相加 No.34
    return sum_n            #返回结果 No.35

def remove_bracket(exp):
    '''
    将表达式中所有的括号都计算出结果,替换原有的表达式,直到这个表达式内不再含有括号
    :param exp:str类型带着括号的表达式'1-2*((60-30+(9-2*5/3+7/3*99/4*2998+10*568/14)*(-40/5))-(-4*3)/(16-3*2))'
    :return:str类型的不带括号的表达式'1-2*-1388335.8476190479'
    '''

    #来自def calculator(exp):
    # 先计算括号内的
    while True:
        ret = re.search('\([^()]+\)', exp)  #1-2*5  通过正则匹配出首尾是括号,中间没有括号的式子 No.4
        if ret:
            no_bracket_exp = ret.group()  # (9-2*5/3+7/3*99/4*2998+10*568/14) 循环匹配出每个最小的括号 No.5
            res = cal_no_bracket(no_bracket_exp)  # (9-2*5/3+7/3*99/4*2998+10*568/14) 把每个最小的括号里面的式子送去运算 No.6
                                                  # res是每个单独的乘除法小式子的结果 No.6 
                                                  # 与cal_no_bracket函数不断交换数据,直到本身找不到括号 返回到本函数 No.18
            exp = exp.replace(no_bracket_exp,str(res))  #用运算出的结果替换运算之前的式子 No.19
        else:break                                      # 式子里没有括号就退出 No.20
    return exp               #exp是已经没有乘除法的式子 返回给调用它的函数 No.21

def calculator(exp):
    '''
    处理原始表达式格式,去掉括号并且进行最后一步计算
    :param exp:原始的字符串格式的表达式
    :return:float类型的结果
    '''
    exp = exp.replace(' ','')   #去掉式子里所有的空格 No.2
    ret = remove_bracket(exp)   #将exp传入函数计算 No.3 ret是已经没有乘除法的式子 No.22
    return cal_no_bracket(ret)  #将已经没有乘除法的式子送出运算 No.23 收到最终结果 No.36

exp = '1 - 2 * ( (60-30 + (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )*(-40/5)) - (-4*3)/ (16-3*2) )'
res = calculator(exp)   #开始进行程序 No.1
print(res,type(res))    # 打印结果 No.37 over

 

posted @ 2019-03-28 22:45  亚里士多缺德  阅读(57)  评论(0)    收藏  举报