一、程序介绍
需求:
开发一个简单的python计算器
1.实现加减乘除及拓号优先级解析
2.用户输入
-1 - 2 *((-60+30+(-40/5)*(-9-2*-5/30-7/3*99/4*2998+10/-568/14))-(-4*-3)/(16-3*2))+3
等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致
程序结构:
函数结构
is_symbol
#判断格式化后的数学表达式 是运算符 还是数字
priority
#优先级比较 栈顶元素,待入栈元素
calculale
#计算最小化的数学表达式 数字 运算符 数字
init_action
#把用户输入的数学表达式 格式化成列表
main
#主函数
二、流程图
三、程序代码
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 4 import re 5 6 def is_symbol(element): #判断格式化后的数学表达式 是运算符 还是数字 7 ''' 8 判断格式化后的数学表达式 是运算符 还是数字 9 如果是运算符 返回 True 10 如果是数字 返回 False 11 :param element: 12 :return: 13 ''' 14 res=False 15 symbol=['+','-','*','/','(',')'] 16 if element in symbol: 17 res=True 18 return res 19 20 21 def priority(top_sym,wait_sym): #优先级比较 栈顶元素,待入栈元素 22 ''' 23 判断传入的 栈顶元素 和 待入栈元素 24 > 取出运算符栈的栈顶,取出两次数字栈的栈顶 进行运算 25 < 加入符号栈栈顶 26 = 取出符号栈栈顶 27 :param top_sym: 28 :param wait_sym: 29 :return: 30 ''' 31 # print('from the priotry : ',ltop_sym,wait_sym) 32 level1=['+','-'] 33 level2=['*','/'] 34 level3=['('] 35 level4=[')'] 36 #运算符栈顶元素为 + - 37 if top_sym in level1: 38 # if wait_sym in level1: #同级别都属于‘+’和‘-’,返回‘>’,计算结果 39 # return '>' 40 # elif wait_sym in level2: #例如 top_sym='-' wait_sym='*' 41 # return '<' 42 # elif wait_sym in level3: #例如 top_sym='-' wait_sym='(' 43 # return '<' 44 # elif wait_sym in level4: #例如 top_sym='-' wait_sym=')' 45 # return '>' 46 # else: 47 # return '>' 48 if wait_sym in level2 or wait_sym in level3: 49 return '<' 50 else: 51 return '>' 52 53 #运算符栈顶元素为 * / 54 elif top_sym in level2: 55 # if wait_sym in level1: #例如 top_sym='*' wait_sym='+' 56 # return '>' 57 # elif wait_sym in level2: #例如 top_sym='*' wait_sym='*' 58 # return '>' 59 # elif wait_sym in level3: #例如 top_sym='*' wait_sym='(' 60 # return '<' 61 # elif wait_sym in level4: #例如 top_sym='*' wait_sym=')' 62 # return '>' 63 # else: 64 # return '>' 65 if wait_sym in level3: 66 return '<' 67 else: 68 return '>' 69 70 #运算符栈栈顶元素为 ( 71 elif top_sym in level3: 72 if wait_sym in level4: #右括号)碰到了(,那么左括号应该弹出栈顶 73 return '=' 74 else: #例如 top_sym='(' wait_sym=‘+’,‘-’,‘*’,‘/’ 75 return '<' #只要栈顶元素为 ( ,等待入栈的元素都应该无条件入栈 76 77 # 运算符栈栈顶元素为 ),没有这种情况 78 79 80 def calculale(num1,symbol,num2): #计算最小化的数学表达式 数字 运算符 数字 81 ''' 82 接收一个最小化的数学表达式,并运算出结果 83 :param num1: 84 :param symbol: 85 :param num2: 86 :return: 87 ''' 88 res=0 89 if symbol == '+': 90 res=num1+num2 91 elif symbol == '-': 92 res=num1-num2 93 elif symbol == '*': 94 res=num1*num2 95 elif symbol == '/': 96 res=num1/num2 97 print('from calculate res is [%s|%s|%s|%s]' %(num1,symbol,num2,res)) 98 return res 99 100 101 def init_action(expression): #把用户输入的数学表达式 格式化成列表 102 # print(expression) 103 expression=re.sub(' ','',expression) #替换掉数学表达式的空格 104 # print(expression) 105 init_l=[i for i in re.split('(\-\d+\.*\d*)',expression) if i] #按照运算符加数字切分列表 106 # print('--->',init_l) 107 expression_l=[] #定义最后存入的格式化列表 108 while True: #循环用户数学表达式的格式化列表,区分负数,数字,运算符 109 if len(init_l) == 0:break #当 列表.pop取完值后 退出循环 110 exp=init_l.pop(0) #从列表0下标开始取元素 111 # print('===>>',exp) 112 if len(expression_l) == 0 and re.search('^\-\d+\.*\d*$',exp): #判断列表是否为空,并且以-数字开头,就是负数 113 expression_l.append(exp) 114 continue 115 if len(expression_l) > 0: #判断列表不为空时 116 if re.search('[\+\-\*\/\(]$',expression_l[-1]): #当前列表最后一个元素是 运算符+-*/( 时 此刻的列表元素就是负数 117 expression_l.append(exp) 118 continue 119 120 new_l=[i for i in re.split('([\+\-\*\/\(\)])',exp) if i] #以运算符为分隔符,切分当前列表元素 121 # print(new_l) 122 expression_l+=new_l 123 # print(expression_l) 124 125 return expression_l 126 127 128 def main(expression_l): #主函数 129 # print('from in the main',expression_l) 130 number_stack=[] 131 symbol_stack=[] 132 for ele in expression_l: 133 # print('-'*20) 134 # print('数字栈',number_stack) 135 # print('运算符栈',symbol_stack) 136 # print('待入栈运算符',ele) 137 138 ret=is_symbol(ele) #传给 is_symbol函数 判断 是运算符 还是数字 139 # 如果是数字 返回False 140 if not ret: 141 #压入数字栈 142 ele=float(ele) 143 number_stack.append(ele) 144 # 如果是运算符 返回True 145 else: 146 #压入运算符栈 147 while True: 148 if len(symbol_stack) == 0: #如果 149 symbol_stack.append(ele) 150 break 151 res=priority(symbol_stack[-1],ele) 152 153 if res == '<': #加入符号栈栈顶 进行下一次判断 154 symbol_stack.append(ele) 155 break 156 if res == '=': #取出符号栈栈顶 进行下一次判断 此时会有 一个左括号.内容.右括号 157 symbol_stack.pop() 158 break 159 if res == '>': #取出运算符栈的栈顶,取出两次数字栈的栈顶,传给给calculale函数 运算出结果 160 symbol=symbol_stack.pop() 161 num2=number_stack.pop() 162 num1=number_stack.pop() 163 number_stack.append(calculale(num1,symbol,num2)) 164 else: #当循环结束时,数字栈底 和 运算符栈底 还有待入栈底的运算符 需要循结束后,取出该3个元素 运算出最终结果 165 symbol = symbol_stack.pop() 166 num2 = number_stack.pop() 167 num1 = number_stack.pop() 168 number_stack.append(calculale(num1, symbol, num2)) 169 170 return number_stack,symbol_stack 171 172 173 if __name__ == '__main__': 174 # expression='-1 - 2 *((-60+30+(-40/5)*(-9-2*-5/30-7/3*99/4*2998+10/-568/14))-(-4*-3)/(16-3*2))+3' 175 while True: 176 print('您可以输入这个数学表达式或者自写数学表达式:-1 - 2 *((-60+30+(-40/5)*(-9-2*-5/30-7/3*99/4*2998+10/-568/14))-(-4*-3)/(16-3*2))+3') 177 expression = input('==>>: ').strip() 178 if len(expression) == 0: continue 179 # expression='-1-2*((-60+30+(-40/5)*(-9-2*-5/30-7/3*99/4*2998+10/-568/14))-(-4*-3)/(16-3*2))+3 180 # expression='-1 - 3 *( -2+3)' 181 expression_l=init_action(expression) #格式化 处理用户输入的数学表达式 成列表 182 # print(expression_l) 183 184 l=main(expression_l) #把格式化后的列表 传入main主函数 185 # print('=====>>',l) 186 print('您的最终结果是:\033[31;1m%s\033[0m' %l[0][0])