Python实现简单的四则运算计算器

发表于 5年以前  | 总阅读数:708 次

一、算法

 1、算法的主要思想就是将一个中缀表达式(Infix expression)转换成便于处理的后缀表达式(Postfix expression),然后借助于栈这个简单的数据结构,计算出表达式的结果。  


 2、关于如何讲普通的表达式转换成后缀表达式,以及如何处理后缀表达式并计算出结果的具体算法描述不在此叙述了,书上有详细的说明。  

二、简易计算器

使用说明

使用该计算器类的简单示例如下:


    # usage
    c = Calculator()
    print('result: {:f}'.formart(c.get_result('1.11+2.22-3.33*4.44/5.55')))
    # output:
    result: 0.666000

测试案例

为了对这个计算器进行有效地检验,设计了几组测试案例,测试结果如下:


    Test No.1: (1.11) = 1.110000
    Test No.2: 1.11+2.22-3.33*4.44/5.55 = 0.666000
    Test No.3: 1.11+(2.22-3.33)*4.44/5.55 = 0.222000
    Test No.4: 1.11+(2.22-3.33)*(4.44+5.55)/6.66 = -0.555000
    Test No.5: 1.11*((2.22-3.33)*(4.44+5.55))/(6.66+7.77) = -0.852992
    Test No.6: (1.11+2.22)*(3.33+4.44)/5.55*6.66 = 31.048920
    Test No.7: (1.11-2.22)/(3.33+4.44)/5.55*(6.66+7.77)/(8.88) = -0.041828
    Test No.8: Error: (1.11+2.22)*(3.33+4.44: missing ")", please check your expression
    Test No.9: Error: (1.11+2.22)*3.33/0+(34-45): divisor cannot be zero
    Test No.10: Error: 12+89^7: invalid character: ^

实现代码

栈的实现

栈实际上就是一个被限制操作的表,所有的操作只能在栈的顶端(入栈、出栈等),以下是使用Python代码实现的简单的栈:


    class Stack(object):
      """
      The structure of a Stack.
      The user don't have to know the definition.
      """
      def __init__(self):
        self.__container = list()
      def __is_empty(self):
        """
        Test if the stack is empty or not
        :return: True or False
        """
        return len(self.__container) == 0
      def push(self, element):
        """
        Add a new element to the stack
        :param element: the element you want to add
        :return: None
        """
        self.__container.append(element)
      def top(self):
        """
        Get the top element of the stack
        :return: top element
        """
        if self.__is_empty():
          return None
        return self.__container[-1]
      def pop(self):
        """
        Remove the top element of the stack
        :return: None or the top element of the stack
        """
        return None if self.__is_empty() else self.__container.pop()
      def clear(self):
        """
        We'll make an empty stack
        :return: self
        """
        self.__container.clear()
        return self

计算器类的实现

在计算器类中,我们将表达式的合法性验证单独放在一个函数中完成,但是实际上如果需要,也可以直接放在中缀表达式转后缀表达式的函数中实现,这样只需要一次遍历表达式即可同时完成验证和转换工作。但是为了保持结构清晰,还是分开来实现比较好,每个函数尽可能最好一件事情才是比较实在的。

在该计算器类中,有很多种极端的情况没有被考虑进去,因为那样的话整个实现的代码会更多。不过,可以在后期为整个类继续扩展,添加新的功能也是可以的。目前实现的就是主要框架,包括基本的错误检测和运算,重点时学习运用栈这个看似简单却强大的数据结构解决问题。


    class Calculator(object):
      """
      A simple calculator, just for fun
      """
      def __init__(self):
        self.__exp = ''
      def __validate(self):
        """
        We have to make sure the expression is legal.
        1. We only accept the `()` to specify the priority of a sub-expression. Notes: `[ {` and `] }` will be
        replaced by `(` and `)` respectively.
        2. Valid characters should be `+`, `-`, `*`, `/`, `(`, `)` and numbers(int, float)
        - Invalid expression examples, but we can only handle the 4th case. The implementation will
        be much more sophisticated if we want to handle all the possible cases.:
          1. `a+b-+c`
          2. `a+b+-`
          3. `a+(b+c`
          4. `a+(+b-)`
          5. etc
        :return: True or False
        """
        if not isinstance(self.__exp, str):
          print('Error: {}: expression should be a string'.format(self.__exp))
          return False
        # Save the non-space expression
        val_exp = ''
        s = Stack()
        for x in self.__exp:
          # We should ignore the space characters
          if x == ' ':
            continue
          if self.__is_bracket(x) or self.__is_digit(x) or self.__is_operators(x) \
              or x == '.':
            if x == '(':
              s.push(x)
            elif x == ')':
              s.pop()
            val_exp += x
          else:
            print('Error: {}: invalid character: {}'.format(self.__exp, x))
            return False
        if s.top():
          print('Error: {}: missing ")", please check your expression'.format(self.__exp))
          return False
        self.__exp = val_exp
        return True
      def __convert2postfix_exp(self):
        """
        Convert the infix expression to a postfix expression
        :return: the converted expression
        """
        # highest priority: ()
        # middle: * /
        # lowest: + -
        converted_exp = ''
        stk = Stack()
        for x in self.__exp:
          if self.__is_digit(x) or x == '.':
            converted_exp += x
          elif self.__is_operators(x):
            converted_exp += ' '
            tp = stk.top()
            if tp:
              if tp == '(':
                stk.push(x)
                continue
              x_pri = self.__get_priority(x)
              tp_pri = self.__get_priority(tp)
              if x_pri > tp_pri:
                stk.push(x)
              elif x_pri == tp_pri:
                converted_exp += stk.pop() + ' '
                stk.push(x)
              else:
                while stk.top():
                  if self.__get_priority(stk.top()) != x_pri:
                    converted_exp += stk.pop() + ' '
                  else:
                    break
                stk.push(x)
            else:
              stk.push(x)
          elif self.__is_bracket(x):
            converted_exp += ' '
            if x == '(':
              stk.push(x)
            else:
              while stk.top() and stk.top() != '(':
                converted_exp += stk.pop() + ' '
              stk.pop()
        # pop all the operators
        while stk.top():
          converted_exp += ' ' + stk.pop() + ' '
        return converted_exp
      def __get_result(self, operand_2, operand_1, operator):
        if operator == '+':
          return operand_1 + operand_2
        elif operator == '-':
          return operand_1 - operand_2
        elif operator == '*':
          return operand_1 * operand_2
        elif operator == '/':
          if operand_2 != 0:
            return operand_1 / operand_2
          else:
            print('Error: {}: divisor cannot be zero'.format(self.__exp))
            return None
      def __calc_postfix_exp(self, exp):
        """
        Get the result from a converted postfix expression
        e.g. 6 5 2 3 + 8 * + 3 + *
        :return: result
        """
        assert isinstance(exp, str)
        stk = Stack()
        exp_split = exp.strip().split()
        for x in exp_split:
          if self.__is_operators(x):
            # pop two top numbers in the stack
            r = self.__get_result(stk.pop(), stk.pop(), x)
            if r is None:
              return None
            else:
              stk.push(r)
          else:
            # push the converted number to the stack
            stk.push(float(x))
        return stk.pop()
      def __calc(self):
        """
        Try to get the result of the expression
        :return: None or result
        """
        # Validate
        if self.__validate():
          # Convert, then run the algorithm to get the result
          return self.__calc_postfix_exp(self.__convert2postfix_exp())
        else:
          return None
      def get_result(self, expression):
        """
        Get the result of an expression
        Suppose we have got a valid expression
        :return: None or result
        """
        self.__exp = expression.strip()
        return self.__calc()
      """
      Utilities
      """
      @staticmethod
      def __is_operators(x):
        return x in ['+', '-', '*', '/']
      @staticmethod
      def __is_bracket(x):
        return x in ['(', ')']
      @staticmethod
      def __is_digit(x):
        return x.isdigit()
      @staticmethod
      def __get_priority(op):
        if op in ['+', '-']:
          return 0
        elif op in ['*', '/']:
          return 1

总结

以上就是利用Python实现简单四则运算计算器的全部内容,希望本文的内容对大家的学习或者工作能有所帮助,如果有疑问大家可以留言交流。

参考

《数据结构与算法(C语言)》上相关章节算法描述

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237229次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8063次阅读
 目录