zoukankan      html  css  js  c++  java
  • 练习-表达式计算(多层括号,加,减,乘,除,整除,取余,幂)

    import re
    
    # 运算字典
    calc = {
        '+': lambda x, y: x + y,  # 加
        '-': lambda x, y: x - y,  # 减
        '*': lambda x, y: x * y,  # 乘
        '/': lambda x, y: x / y,  # 除
        '%': lambda x, y: x % y,  # 取余数
        '//': lambda x, y: x // y,  # 整除
        '^': lambda x, y: x ** y  # 幂(不知道是不是bug,方式不同结果不同,最下面有演示)
    }
    
    
    # 判断优先级函数
    def order(lis=[]):
        # 列表开头有'-'说明第一个数是负数
        if lis[0] == '-':
            lis.pop(0)
            lis[0] = -float(lis[0])
        while len(lis) != 1:  # 未得到最终结果就继续执行
            for i in range(len(lis)):
                # 判断是否运算符
                muldiv = re.search(r'[^*/%+-]/?$', str(lis[i]))
                if muldiv:
                    # 判断当前是否加,减运算
                    if re.search(r'[+-]', str(lis[i])):
                        # 判断后续是否有优先级高的幂,乘,除,求余,整除运算
                        if re.search(r'[^*/%]/?', str(lis)):
                            continue
                    # 判断当前是否乘,除,求余,整除运算
                    elif re.search(r'[*/%]/?', str(lis[i])):
                        # 判断后续是否有优先级高的幂运算
                        if re.search(r'[^]', str(lis)):
                            continue
                    num1 = float(lis[i - 1])  # 取参数1
                    # 在i是符号的情况下,出现'-',说明下个数是负数,
                    if lis[i + 1] == '-':
                        lis.pop(i + 1)
                        lis[i + 1] = -float(lis[i + 1])
                    num2 = float(lis[i + 1])  # 取参数2
                    result = calc[muldiv.group()](num1, num2)  # 按运算符进行运算
                    for m in range(2):  # 删除已运算完的表达式
                        lis.pop(i)
                    lis[i - 1] = result  # 将结果加入表达式
                    break  # 返回重新开始,因为索引位置已发生改变,不适合继续取值
        return lis
    
    
    # 主函数
    def operation(exp):
        # 统一格式化表达式
        exp = exp.replace(' ', '').replace(')(', ')*(')
        exp = exp.replace('++', '+').replace('--', '+')
        exp = exp.replace('+-', '-').replace('-+', '-')
        exp = exp.replace('**', '^')
        # 正则分割字符串
        exp = re.findall(r'd+(?:.d+)?|[D+]/?', exp)
        while '(' in exp:  # 判断有没有括号
            # 用循环来寻找匹配的括号,执行完括号内表达式就退出循环
            for i in range(len(exp)):
                if exp[i] == '(':
                    if i > 0 and re.search(r'd+(?:.d+)?', str(exp[i - 1])):
                        exp.insert(i, '*')  # 将类似2()形式的,改成2*()形式
                        break
                    start = i  # 记录最后一个"("位置
                elif exp[i] == ')':
                    fir = exp[:start]  # 切片列表左边
                    mid = exp[start + 1:i]  # 切片要计算的中间列表
                    end = exp[i + 1:]  # 切片列表右边
                    mid = order(mid)  # 判断优先级计算,得出计算结果
                    exp = fir + mid + end  # #将括号内表达式计算完后,进行列表拼接
                    print(str(exp).replace(',', '').replace("'", ''))
                    break
                    # 跳出for循环,不再进行下一组括号计算(因为原列表已改变,索引也改变,不适合下次取值)
        else:  # 没括号,直接执行计算
            order(exp)
        return float(exp[0])
    
    if __name__ == '__main__':
        l = "-2.5*((3.562**2 + 5*-60//-2)*(3*-5/6-9%-10//3))"
        # 分解步骤如下
        # - 2.5 * (162.68784399999998 * (3 * - 5 / 6 - 9 % - 10 // 3))
        # - 2.5 * (162.68784399999998 * -1.5)
        # - 2.5 * -244.03176599999998
        # 610.0794149999999
        ret = operation(l)
        print('内置函数:%s' % eval(l))
        print('自写函数:%s' % ret)
    
    
        # 同样都是幂运算,结果却不相同
        num1 = -3.562
        num2 = 8
        print('eval:%F     数字:%F    变量:%F    POW:%F' %
              (eval('-3.562**8'), -3.562**8, num1**num2, pow(-3.562, 8)))
    

      

  • 相关阅读:
    第四章之Hadoop I/O
    第五章之MapReduce应用开发
    数据预处理
    SQL Server Migration Assistant for MySQL!
    【转载】.NET设计模式之工厂方法模式(Factory Method)
    "lc.exe"已退出 代码为1 的解决方法
    【转载】.NET设计模式之抽象工厂模式(Abstract Factory)
    【转载】(收藏)《博客园精华集》分类索引
    【转载】.NET设计模式之观察者模式(Observer Pattern)
    【转载】使用Visual Studio 2010调试断点不起作用的问题解决办法(AutoCAD)
  • 原文地址:https://www.cnblogs.com/xh4528/p/6539403.html
Copyright © 2011-2022 走看看