正则表达式实现计算器

 
# __author: busensei
# data: 2018/8/15

from functools import reduce
import re


def cal_atomexp(atom_exp):
    # 计算乘除法
    if '*' in atom_exp:
        a, b = atom_exp.split('*')
        atom_res = float(a) * float(b)
    elif '/' in atom_exp:
        a, b = atom_exp.split('/')
        atom_res = float(a) / float(b)
    return str(atom_res)


def cal_muldiv(inner_bracket):
    while True:  # 计算括号里的所有乘除法
        # 匹配第一个乘除法  inner_bracket = (9-2*5/3+7/3*99/4*2998+10*568/14)
        ret = re.search('\d+(\.\d+)?[*/]-?\d+(\.\d+)?', inner_bracket)
        if not ret: break
        atom_exp = ret.group()  # 获取乘除法表达式  # 2*5
        atom_res = cal_atomexp(atom_exp)  # 计算乘除法的函数,得到结果  10.0
        inner_bracket = inner_bracket.replace(atom_exp, str(atom_res))
        # inner_bracket = (9-10.0/3+7/3*99/4*2998+10*568/14)
        # 将得到的结果与匹配到的表达式进行兑换
    return inner_bracket  # 返回的是一个纯加减法组成的算式


def cal_addsub(inner_bracket):
    # 计算括号中的所有加减法
    # (9 - 3.3333333333333335 + 173134.50000000003 + 405.7142857142857)
    ret_l = re.findall('[-+]?\d+(?:\.\d+)?', inner_bracket)
    return str(reduce(lambda a, b: float(a) + float(b), ret_l))


def format_exp(exp):
    # 给表达式做格式化
    exp = exp.replace('--', '+')
    exp = exp.replace('+-', '-')
    exp = exp.replace('++', '+')
    exp = exp.replace('-+', '-')
    return exp


def main(s):
    s = s.replace(' ', '')
    while True:
        # 找最内层的小括号
        inner_bracket = re.search('\([^()]+\)', s)
        if not inner_bracket: break  # 找不到小括号了就退出
        inner_bracket = inner_bracket.group()
        inner_bracket_bak = inner_bracket
        inner_bracket = cal_muldiv(inner_bracket)  # 括号内的 : 计算了所有乘除法,只剩下加减法的表达式
        inner_bracket = format_exp(inner_bracket)
        res = cal_addsub(inner_bracket)
        s = s.replace(inner_bracket_bak, res)
    s = cal_muldiv(s)
    s = format_exp(s)
    s = cal_addsub(s)
    return s


# s = '1-2*((60-30 +(9-2*5/3+7/3*99/4*2998+10*568/14)*(-40 / 5))-(-4*3)/(16-3*2))'
s = input('>>>')
print(main(s))
print(eval(s))

 

 

 

'''
计算流程:
1.将括号表达式(内部不包含括号)匹配出来
2.计算括号表达式的值,用计算值替换原括号表达式
    计算处理流程:
    1)从左至右匹配,匹配出乘法或除法表达式,计算出值,塞回去替换匹配的内容
    2)乘除法运算都已处理完,对剩下表达式从左至右匹配
    3)匹配一个加法或减法运算式,计算出值,塞回去,替换匹配的表达式
    4)直到没有匹配运算式,停止,本轮括号表达式计算替换值流程完成
3.再次进行括号表达式(内部不包含括号)匹配
4.重复2
5.直到匹配不出括号表达式,直接对剩余运算式进行乘除加减处理
'''
import re

p1 = re.compile(r'\+\s*?-|-\s*?\+')  # 匹配'+-或-+' 匹配-+是为了处理用户输入原始表达式中有-+的情况
p2 = re.compile(r'-\s*?-')  # 匹配'--'


def process_multi_divis(s):
    pattern = re.compile(r'-?\d+(?:\.?\d+)?\s*?[*/]{1}\s*?-?\s*?\d+(?:\.?\d+)?')  # 匹配 *,/,*-,/- 四种情况
    while 1:
        result_process_p1 = re.sub(p1, '-', s)
        s = re.sub(p2, '+', result_process_p1)
        r = re.search(pattern, s)
        if r:
            r = r.group()
            if '*' in r:
                a, b = r.split('*')
                result = float(a.strip()) * float(b.strip().replace(' ', ''))  # 5 *- 6这种表达式,去除负号与数字之间空格
            elif '/' in r:
                a, b = r.split('/')
                result = float(a.strip()) / float(b.strip().replace(' ', ''))
            s = s.replace(r, str(result))
        else:
            return s


def process_plus_reduce(s):
    pattern = re.compile(r'-?\d+(?:\.?\d+)?\s*?[+-]{1}\s*?\d+(?:\.?\d+)?')
    while 1:
        result_process_p1 = re.sub(p1, '-', s)
        s = re.sub(p2, '+', result_process_p1)
        r = re.search(pattern, s)
        if r:
            r = r.group()
            if '+' in r:
                a, b = r.split('+')
                result = float(a.strip()) + float(b.strip())
            elif '-' in r:
                if r.startswith('-'):  # 处理类似 -5-10 这种表达式
                    nums = r.split('-')
                    a, b = nums[1], nums[2]
                    result = - float(a.strip()) - float(b.strip())
                else:
                    a, b = r.split('-')
                    result = float(a.strip()) - float(b.strip())
            s = s.replace(r, str(result), 1)  # 只替换一次,避免遇到1+1+1+1这样的表达式,发生多次替换的情况
        else:
            return s


def process_parentheses(s):
    pattern = re.compile(r'\([^(]+?\)')  # 匹配最内层括号
    while 1:
        r = re.findall(pattern, s)
        if r:
            for item in r:
                expression = item[1:-1]  # 去掉首尾括号
                r1 = process_multi_divis(expression)  # 处理乘除法
                r2 = process_plus_reduce(r1)  # 处理加减法
                s = s.replace(item, r2)  # 处理完成,替换计算结果后,表达式中可能会存在'+-','--'这种运算符,需匹配进行替换; '+-'替换为'-','--'替换为'+'
            result_process_p1 = re.sub(p1, '-', s)
            s = re.sub(p2, '+', result_process_p1)
        else:
            return s


def main():
    expression = input('请输入要计算的表达式:')
    result_step1 = process_parentheses(expression)  # 处理括号
    result_step2 = process_multi_divis(result_step1)  # 计算乘除法
    final_result = process_plus_reduce(result_step2)  # 计算加减法
    print('计算结果:', final_result)



if __name__ == '__main__':
    while 1:
        main()

 

posted @ 2018-03-13 21:18  小学弟-  阅读(485)  评论(0编辑  收藏  举报