简单版计算器

解题思路

    一、计算器运算规则

            优先级                    匹配格式

    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)

 

posted @ 2016-09-27 11:23  财经知识狂魔  阅读(339)  评论(0编辑  收藏  举报