通过正则以及re模块设计一个计算器

#实现能计算类似
a = '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

def count_all(formula):
    while True:
        # 取出第一个最小的括号公式\([^()]+\)
        min_brackets = re.search('\([^()]+\)', formula)
        if min_brackets:
            ret = min_brackets.group()
            print('一个最小的括号公式(min_brackets): ', min_brackets.group())
            # 接着开始去括号,并计算,建议写函数,将这个字符串传进函数,做去括号
            new_ret = count_min_brackets(ret)  # 返回一个
            # 接受返回值,替换掉带括号的公式
            formula = formula.replace(ret, new_ret)
            print('替换掉最小括号后的公式:', formula)
            # 发现公式里包含了+-号,需要取消加减号,写函数来替换
            formula = replace_sign(formula)
            print('替换掉+-或--后的公式', formula)
            # 接着再把新的公司再次放到min_brackets里找到最小的公式,这里开始使用while循环
        else:
            print("已经没有括号了", formula)
            # 开始计算结果
            formula = count_min_brackets(formula)

            print('最后的结果是:', formula)
            break

# 去除+-或--号
def replace_sign(formula):
    if '+-' in formula:
        formula = formula.replace('+-','-')
    if '--' in formula:
        formula = formula.replace('--','+')
    return formula

#计算加减乘除
def count_brackets(formula):
    if '*' in formula:
        a,b = formula.split('*')
        value = float(a)*float(b)
        print('这是乘法的结果:',str(value))
        return str(value)
    elif '/' in formula:
        a,b = formula.split('/')
        value = float(a)/float(b)
        print('这是除法的结果:',str(value))
        return str(value)
    # 开始做加减法,进行累加
    else:
        ret = re.findall('-?\d+\.?\d+|\d+',formula)
        sum = 0
        for i in ret:
            sum += float(i)
        return str(sum)


#去括号,调用计算函数,得出结果
def count_min_brackets(formula):
    # 去括号
    formula= formula.strip('()')
    print("去括号后的公式",formula)
    # 接着提取出公式里的首个乘除,并开始计算
    while True: # 需要重复检测是否存在乘除,所以加上循环
        brackets = re.search('\d*\.?\d+[*/]-?\d*\.?\d',formula)
    # 用正则得出结果   22.222*100/-22.222*100+100/10
    # 正则解析:数字(有可能是浮点数222.222)开头是数字\d(可能是多位数,所以加*)\.?(有可能是浮点数,肯定只有一个'.',采用0或1次匹配)\d*(以数字结尾),则可以匹配出22.222
    # 接着使用字符组[],需要匹配乘除即[*/]
    # 接着有可能出现负数:先匹配0或1次-?后面的是\d(可能是多位数,所以加*)\.?(有可能是浮点数,肯定只有一个'.',采用0或1次匹配)\d*(以数字结尾),则可以匹配出-22.222

        if brackets:
            ret = brackets.group()
            print('提取出公式中的乘除:',ret)
            # 开始计算公式,可以使用函数来计算加减乘除
            value = count_brackets(ret)
            print('最小公式的结果:',value)
            # 将结果返回回去,替换掉公式
            formula = formula.replace(ret,value)
            print('替换公式后返回的值',formula)
            # 后期执行完后,发现执行到最后有个1--2776670.480952381,存在一个‘- -’,所以要加个转换为'+'
            formula = replace_sign(formula)
            #return new_ret
        else:
            print('没有乘除法了:',formula)
            # 开始计算纯粹加减法了,可以利用正则取出正负数,-?\d+\.?\d+|\d+ 开始做累加
            formula = count_brackets(formula)
            print('这是加减法得出的结果',formula)
            return formula
            break



a = '1 - 2 * ( (60-30   +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
# 去空格
b = a.replace(' ','')
print(b)
count_all(b)
笔者的思路

请用这个网站的正则测试 http://tool.chinaz.com/regex/

posted on 2019-03-09 16:30  Jerry-Wang  阅读(143)  评论(0)    收藏  举报