Python堆栈实现计算器

一、程序介绍

需求:

开发一个简单的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])
View Code

 





posted @ 2017-10-28 01:16  朱志文  阅读(1756)  评论(0编辑  收藏  举报