zoukankan      html  css  js  c++  java
  • 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('您的最终结果是:33[31;1m%s33[0m' %l[0][0])
    View Code




  • 相关阅读:
    Flink Table环境配置、读取外部数据(File、Kafka)以及查询转换
    Flink之Table初探
    Flink之Watermarks
    Flink之ProcessFunction侧输出流
    Flink之ProcessFunction案例
    Flink之Mysql数据CDC
    Express ejs 模板做的 app.js 文件
    金额转换文章(100=>零佰)
    将 音频流(MP3流)并进行播放
    浅谈MySQL(一):存储引擎与索引
  • 原文地址:https://www.cnblogs.com/zhuzhiwen/p/7745802.html
Copyright © 2011-2022 走看看