zoukankan      html  css  js  c++  java
  • 【Python】使用正则表达式实现计算器练习

    已知有以下这样一个不太友好的公式:

    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) )

    我们使用正则表达式的基础来练习,将此结果计算出来。

    代码如下:

      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 
      4 import re
      5 import functools
      6 
      7 def minus_operator_handler(formula):
      8     '''处理一些特殊的减号运算'''
      9     minus_operators = re.split("-",formula)
     10     calc_list = re.findall("[0-9]",formula)
     11     if minus_operators[0] == '':    # 第一个值肯定是负号
     12         calc_list[0] = '-%s' % calc_list[0]
     13     result = functools.reduce(lambda x,y: float(x) - float(y),calc_list)
     14     print(" - [%s] of result is : " % formula, result )
     15     return result
     16 
     17 def handle_minus_in_list(operator_list,calc_list):
     18     '''
     19     有的时候把算术符和值分开后,会出现这种情况  ['-', '-', '-'] [' ', '14969037.996825399 ', ' ', '12.0/ 10.0 ']
     20     这需要把第2个列表中的空格都变成负号并与其后面的值拼起来
     21     '''
     22     for index,item in enumerate(calc_list):
     23         if item == '':
     24             calc_list[index+1] = item + calc_list[index+1].strip()
     25 
     26 def compute_mutiply_and_dividend(formula):
     27     '''计算乘除的内容,这里传进来的是字符串'''
     28     # 找出所有带*、/符号的内容
     29     operators = re.findall("[*/]",formula)
     30     # 以*、/为分隔符,取出所有排除掉*、/的内容
     31     calc_list = re.split("[*/]",formula)
     32     # 结果初始化未None
     33     result = None
     34     # 遍历显示数组中的索引号(index)、内容(i)
     35     for index,i in enumerate(calc_list):
     36         if result:    # 代表不是第一次循环
     37             if operators[index-1] == "*":
     38                 result *= float(i)
     39             elif operators[index-1] == "/":
     40                 result /= float(i)
     41         else:
     42             result = float(i)
     43     print("[%s] of result is : " %formula, result)
     44     return result
     45 
     46 def handle_special_occactions(plus_and_minus_operators,multiply_and_dividend):
     47     '''有时会出现这种情况 , ['-', '-'] ['1 ', ' 2 * ', '14969036.7968254'],2*...后面这段实际是 2*-14969036.7968254,需要特别处理下'''
     48     # 遍历显示数组multiply_and_dividend中的索引号(index)、内容(i)
     49     for index,i in enumerate(multiply_and_dividend):
     50         # 清除空格、空白
     51         i = i.strip()
     52         # 如果 内容的结尾是*、/
     53         if i.endswith("*") or i.endswith("/"):
     54             multiply_and_dividend[index] = multiply_and_dividend[index] + plus_and_minus_operators[index] + multiply_and_dividend[index+1]
     55             del multiply_and_dividend[index+1]
     56             del plus_and_minus_operators[index]
     57     return plus_and_minus_operators,multiply_and_dividend
     58 
     59 def remove_addsubtract(formula):
     60     '''将加减组合的符号替换成合并后的符号'''
     61     formula = formula.replace("++","+")
     62     formula = formula.replace("--","+")
     63     formula = formula.replace("+-","-")
     64     formula = formula.replace("-+","-")
     65     formula = formula.replace("- -","+")
     66     return formula
     67 
     68 def compute(formula):
     69     '''这里计算不带括号的内容'''
     70     # 去掉外层的括号
     71     formula = formula.strip("()")    # strip是去除的函数
     72     # 将加减组合的符号替换成合并后的符号
     73     formula = remove_addsubtract(formula)
     74     # 找出替换后剩余的所有带+、-符号的内容
     75     plus_and_minus_operators = re.findall("[+-]",formula)
     76     # 以+、-为分隔符,取出所有排除掉+、-的内容,即取出所有*/的内容
     77     multiply_and_dividend = re.split("[+-]",formula)
     78     if len(multiply_and_dividend[0].strip()) == 0:    # 代表这肯定是个减号
     79         multiply_and_dividend[1] = plus_and_minus_operators[0] + multiply_and_dividend[1]
     80         del multiply_and_dividend[0]
     81         del plus_and_minus_operators[0]
     82     plus_and_minus_operators,multiply_and_dividend = handle_special_occactions(plus_and_minus_operators,multiply_and_dividend)
     83     # 遍历显示数组multiply_and_dividend中的索引号(index)、内容(i)
     84     for index,i in enumerate(multiply_and_dividend):
     85         if re.search("[*/]",i):
     86             calc_inside_result = compute_mutiply_and_dividend(i)
     87             multiply_and_dividend[index] = calc_inside_result
     88 
     89     '''开始运算+、-'''
     90     print(multiply_and_dividend,plus_and_minus_operators)
     91     total_result = None    # 初始化total_result
     92     # 遍历显示数组multiply_and_dividend中的索引号(index)、内容(item)
     93     for index,item in enumerate(multiply_and_dividend):
     94         if total_result:    # 代表不是第一次循环
     95             if plus_and_minus_operators[index-1] == "+":
     96                 total_result += float(item)
     97             elif plus_and_minus_operators[index-1] == "-":
     98                 total_result -= float(item)
     99         else:
    100             total_result = float(item)
    101     print("[%s] of result is : " %formula,total_result)
    102     return total_result
    103 
    104 def calc(formula):
    105     '''计算程序主入口, 主要逻辑是先计算括号里的值,算出来后再算乘除,再算加减'''
    106     #给括号的状态设置初始值,假定括号存在
    107     parenthesis_flag = True
    108     #初始化运算结果为None,还没开始运算
    109     calc_result = None
    110     while parenthesis_flag:
    111         #找到最里面一层的括号。正则表达式:()中间没有()的所有字符
    112         inside = re.search("([^()]*)",formula)
    113         if inside:
    114             # 先计算括号里面的值
    115             calc_inside_result = compute(inside.group())
    116             formula = formula.replace(inside.group(),str(calc_inside_result))
    117         else:
    118             print('33[41;1m~~~没括号了~~~33[0m')
    119             print('The End Result is : ',compute(formula))
    120             # 公式中的括号都被剔除了
    121             parenthesis_flag = False
    122 
    123 #程序的入口
    124 if __name__ == '__main__':
    125     result = 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) )")
  • 相关阅读:
    OpenCASCADE Chamfer 3D Basics
    OpenCASCADE Chamfer 2D
    .NetCore 连接 Oracle 数据库,直接C# 或者 ORM框架(EFCore、XPO)
    心内科疾病指南
    HttpClient 调用 RestAPI 接口的用法
    在 Blazor 应用中使用 DevExtreme widgets
    2021 最近一次检查甘油三脂,验证苯扎贝特的效果。
    紫鹊界本味湘菜,
    如何Rest接口获取网上的股票数据,有哪些资源?-- 推荐Tushare金融数据
    优秀常用的「资源搜索网站」,收藏
  • 原文地址:https://www.cnblogs.com/BIGMOM/p/6011367.html
Copyright © 2011-2022 走看看