已知有以下这样一个不太友好的公式:
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('\033[41;1m~~~没括号了~~~\033[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) )")