• Python-Basis-12th


    周三,晴,记录生活分享点滴

    参考博客:https://www.cnblogs.com/alex3714/articles/5169958.html

    Python版本:3.5

    计算器

    需求

    1. 实现加减乘除及括号优先级解析

    2. 用户输入 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
    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("33[33;1m减号[%s]处理结果:33[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("33[31;1m[%s]运算结果=33[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("33[32;1m[%s]运算结果:33[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('33[41;1m----没括号了...---33[0m')
    
                print('
    
    33[42;1m最终结果:33[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) )")

    输出

    # [2*3]运算结果= 6.0
    # [5/3]运算结果= 1.6666666666666667
    # [40*4/2]运算结果= 80.0
    # [3/5]运算结果= 0.6
    # [6*3]运算结果= 18.0
    # ['-9', '2', '5', 6.0, 1.6666666666666667, 80.0, 0.6, 18.0] ['-', '-', '-', '-', '-', '-', '+']
    # [-9-2-5-2*3-5/3-40*4/2-3/5+6*3]运算结果: -86.26666666666667
    # [2*5/3 ]运算结果= 3.3333333333333335
    # [ 7 /3*99/4*2998 ]运算结果= 173134.50000000003
    # [10 * 568/14 ]运算结果= 405.7142857142857
    # ['-9', '2', '5', 3.3333333333333335, 173134.50000000003, 405.7142857142857] ['-', '-', '-', '+', '+']
    # [-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ]运算结果: 173520.88095238098
    # [86.26666666666667 * 173520.88095238098]运算结果= 14969067.996825399
    # ['60', '30 ', 14969067.996825399] ['-', '-']
    # [60-30 -86.26666666666667 * 173520.88095238098]运算结果: -14969037.996825399
    # [-4*3]运算结果= -12.0
    # [-12.0] []
    # [-4*3]运算结果: -12.0
    # [3*2]运算结果= 6.0
    # ['16', 6.0] ['-']
    # [16-3*2]运算结果: 10.0
    # [12.0/ 10.0 ]运算结果= 1.2
    # ['-14969037.996825399 ', 1.2] ['+']
    # [ -14969037.996825399 +12.0/ 10.0 ]运算结果: -14969036.7968254
    # ----没括号了...---
    # [ 2 * -14969036.7968254]运算结果= -29938073.5936508
    # ['1 ', -29938073.5936508] ['-']
    # [1 - 2 * -14969036.7968254]运算结果: 29938074.5936508
     
    
    # 最终结果: 29938074.5936508
  • 相关阅读:
    关于sqrt函数的使用
    电子商务
    随笔
    哈哈
    整体管理
    软件产品质量特性
    问题
    风险
    antd
    Flex布局大作用
  • 原文地址:https://www.cnblogs.com/chungzhao/p/13037263.html
Copyright © 2020-2023  润新知