Day19

本节内容:

1.使用正则表达式实现计算器的功能

一.计算器

# -*- coding: utf-8 -*-
# @Time    : 2018/8/29 15:46
# @Author  : yh
# @FileName: 计算器.py
# s="1 - 2 * ((60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))"
# #思路:
# #1) 对s做规范化处理
# #2)
# import re
# #检测非法字符
# def check(s):
#     flag=True
#     if re.findall('[a-zA-Z]',s):
#         print('Invalid')
#         flag=False
#     return flag
# #格式化处理
# def format(s):
#     s=s.replace(' ','')
#     s=s.replace('++','+')
#     return s
# def cal_mul_div(s):#(2+0.5/3.9)
#     ret1=re.search('\d+\.?\d* [*/] \d+\.?\d*',s).group()#[*/]匹配乘或除
#     x,y=re.split('[*/]',ret)#'0.5','3.9'
#     ret2=float(x)/float(y)
#     s.replace(ret1,ret2)
#     return s
# def cal_add_sub(s):
#     return s
#
#
# #检测输入的字符是否合法
# if check(s):
#     strs=format(s)#获取了一个新的字符串
#     while re.search('\('):
#         #匹配最里层的括号
#         strs=re.search('\([^()]+\)',strs)
#         #计算
#         strs=cal_mul_div(strs)#计算乘除法
#         strs=cal_add_sub(strs)#计算加减法
#     #处理的是没有括号的运算
#     else:#当while条件不满足走else语句
#         strs = cal_mul_div(strs)  # 计算乘除法
#         strs = cal_add_sub(strs)  # 计算加减法
#
#
import re
import functools
def minus_operator_handler(formula):
    '''处理一些特殊的减号运算'''
    minus_operators = re.split("-", formula)
    calc_list = re.findall("[0-9]", formula)
    if minus_operators[0] == '':  # 第一值肯定是负号
        calc_list[0] = '-%s' % calc_list[0]
    res = functools.reduce(lambda x, y: float(x) - float(y), calc_list)
    print("\033[33;1m减号[%s]处理结果:\033[0m" % formula, res)
    return res
def remove_duplicates(formula):
    formula = formula.replace("++", "+")
    formula = formula.replace("+-", "-")
    formula = formula.replace("-+", "-")
    formula = formula.replace("--", "+")
    formula = formula.replace("- -", "+")
    return formula
def compute_mutiply_and_dividend(formula):
    '''算乘除,传进来的是字符串噢'''
    operators = re.findall("[*/]", formula)
    calc_list = re.split("[*/]", formula)
    res = None
    for index, i in enumerate(calc_list):
        if res:
            if operators[index - 1] == "*":
                res *= float(i)
            elif operators[index - 1] == "/":
                res /= float(i)
        else:
            res = float(i)

    print("\033[31;1m[%s]运算结果=\033[0m" % formula, res)
    return res
def handle_minus_in_list(operator_list, calc_list):
    '''有的时候把算术符和值分开后,会出现这种情况  ['-', '-', '-'] [' ', '14969037.996825399 ', ' ', '12.0/ 10.0 ']
       这需要把第2个列表中的空格都变成负号并与其后面的值拼起来,恶心死了
    '''
    for index, i in enumerate(calc_list):
        if i == '':  # 它其实是代表负号,改成负号
            calc_list[index + 1] = i + calc_list[index + 1].strip()
def handle_special_occactions(plus_and_minus_operators, multiply_and_dividend):
    '''有时会出现这种情况 , ['-', '-'] ['1 ', ' 2 * ', '14969036.7968254'],2*...后面这段实际是 2*-14969036.7968254,需要特别处理下,太恶心了'''
    for index, i in enumerate(multiply_and_dividend):
        i = i.strip()
        if i.endswith("*") or i.endswith("/"):
            multiply_and_dividend[index] = multiply_and_dividend[index] + plus_and_minus_operators[index] + \
                                           multiply_and_dividend[index + 1]
            del multiply_and_dividend[index + 1]
            del plus_and_minus_operators[index]
    return plus_and_minus_operators, multiply_and_dividend
def compute(formula):
    '''这里计算是的不带括号的公式'''
    formula = formula.strip("()")  # 去除外面包的拓号
    formula = remove_duplicates(formula)  # 去除外重复的+-号
    plus_and_minus_operators = re.findall("[+-]", formula)
    multiply_and_dividend = re.split("[+-]", formula)  # 取出乘除公式
    if len(multiply_and_dividend[0].strip()) == 0:  # 代表这肯定是个减号
        multiply_and_dividend[1] = plus_and_minus_operators[0] + multiply_and_dividend[1]
        del multiply_and_dividend[0]
        del plus_and_minus_operators[0]

    plus_and_minus_operators, multiply_and_dividend = handle_special_occactions(plus_and_minus_operators,
                                                                                multiply_and_dividend)
    for index, i in enumerate(multiply_and_dividend):
        if re.search("[*/]", i):
            sub_res = compute_mutiply_and_dividend(i)
            multiply_and_dividend[index] = sub_res

    # 开始运算+,-
    print(multiply_and_dividend, plus_and_minus_operators)
    total_res = None
    for index, item in enumerate(multiply_and_dividend):
        if total_res:  # 代表不是第一次循环
            if plus_and_minus_operators[index - 1] == '+':
                total_res += float(item)
            elif plus_and_minus_operators[index - 1] == '-':
                total_res -= float(item)
        else:
            total_res = float(item)
    print("\033[32;1m[%s]运算结果:\033[0m" % formula, total_res)
    return total_res
def calc(formula):
    '''计算程序主入口, 主要逻辑是先计算拓号里的值,算出来后再算乘除,再算加减'''
    parenthesise_flag = True
    calc_res = None  # 初始化运算结果为None,还没开始运算呢,当然为None啦
    while parenthesise_flag:
        m = re.search("\([^()]*\)", formula)  # 找到最里层的拓号
        if m:
            # print("先算拓号里的值:",m.group())
            sub_res = compute(m.group())
            formula = formula.replace(m.group(), str(sub_res))
        else:
            print('\033[41;1m----没拓号了...---\033[0m')

            print('\n\n\033[42;1m最终结果:\033[0m', compute(formula))
            parenthesise_flag = False  # 代表公式里的拓号已经都被剥除啦
if __name__ == '__main__':
    # res = calc("1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")
    res = calc(
        "1 - 2 * ( (60-30 +(-9-2-5-2*3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")

 

posted on 2018-08-29 16:45  summer666  阅读(108)  评论(0)    收藏  举报