一、算法

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语言)》上相关章节算法描述

python实现简单的四则运算_Python实现简单的四则运算计算器相关推荐

  1. c语言实现爬虫功能,用C/C 扩展Python语言_python 调用c语言 python实现简单爬虫功能_python实现简单爬虫...

    用C/C 扩展Python语言 Python是一门功能强大的脚本语言,它的强大不仅表现在功能上,还表现在其扩展性上.她提供大量的API以方便程序员利用C/C++对Python进行扩展.因为执行速度慢几 ...

  2. python编程超市购物系统_python实现简单购物车系统(练习)

    #!Anaconda/anaconda/python#coding: utf-8 #列表练习,实现简单购物车系统 product_lists= [('iphone',5000), ('computer ...

  3. python简易爬虫课程设计_python实现简单爬虫功能的示例

    在我们日常上网浏览网页的时候,经常会看到一些好看的图片,我们就希望把这些图片保存下载,或者用户用来做桌面壁纸,或者用来做设计的素材. 我们最常规的做法就是通过鼠标右键,选择另存为.但有些图片鼠标右键的 ...

  4. python最简单的架构_Python实现简单状态框架的方法

    本文实例讲述了Python实现简单状态框架的方法.分享给大家供大家参考.具体分析如下: 这里使用Python实现一个简单的状态框架,代码需要在python3.2环境下运行 复制代码 代码如下: fro ...

  5. python tcp协议加代理_python实现简单的TCP代理服务器

    本文实例讲述了python实现简单的TCP代理服务器的方法,分享给大家供大家参考. 具体实现代码如下: # -*- coding: utf-8 -*- ''' filename:rtcp.py @de ...

  6. python能做哪些客户端_Python 实现简单的客户端认证

    问题 你想在分布式系统中实现一个简单的客户端连接认证功能,又不想像SSL那样的复杂. 解决方案 可以利用 hmac 模块实现一个连接握手,从而实现一个简单而高效的认证过程.下面是代码示例: impor ...

  7. python层次聚类法画图_Python实现简单层次聚类算法以及可视化

    本文实例为大家分享了Python实现简单层次聚类算法,以及可视化,供大家参考,具体内容如下 基本的算法思路就是:把当前组间距离最小的两组合并成一组. 算法的差异在算法如何确定组件的距离,一般有最大距离 ...

  8. python获取手机通知栏消息_Python编写简单的通知栏脚本启动工具

    随着自己编写的脚本与安装的工具越来越多,电脑的桌面和文件夹也越来越乱了. 就在前几天因为一个不小心,我把自己的一个项目给删了,所以决定将电脑整理一下. 不过这一整理我很多脚本和工具的位置我就忘记了,所 ...

  9. python和gui结合实例_Python GUI —— 简单例子+讲解

    这篇文章会给大家仔细讲解几个Python GUI的例子. 创建简单的GUI应用 from tkinter import * window = Tk() window.title("Hello ...

最新文章

  1. 我们是如何使用 PingCode Flow 实现研发自动化管理的?
  2. android 打包hbuilder 高德地图加载不出来_十一黄金周地图很忙:百度获央视报道,高德忙道歉,究竟谁好用?...
  3. 图灵2010.06书讯
  4. Linux_SELinux使用
  5. java虚拟机类加载机制_《深入理解java虚拟机》学习笔记一/类加载机制
  6. JPA规范:一对多、一对一、多对多的双向关联与级联操作以及JPA联合主键
  7. 使用JDK 8轻松进行细粒度排序
  8. Git迁移 从SVN到Git
  9. android触摸指纹会触发按键功能,Android P新特性:利用触摸指纹识别器能阻止手机息屏...
  10. 牛客 XOR和(找规律)
  11. PyQt5笔记(01) -- 创建空白窗体
  12. 植物大战僵尸全明星服务器维修多长时间,植物大战僵尸全明星常见问题FAQ详解...
  13. C++调用caffe分类模型-Opencv3.4.3
  14. 转置矩阵使用T,Hermite矩阵、正交矩阵、酉矩阵、奇异矩阵、正规矩阵、幂等矩阵
  15. slitaz linux 包管理器,SliTaz
  16. 防火墙中的DMZ区域,Trust区域,Untrust区域
  17. 实验室新生成长指南[2.2.1] · 连接器
  18. 水星无线wan服务器无反应,怎么解决水星路由器WAN口获取不到IP地址
  19. Oracle数据库类毕业论文文献有哪些?
  20. 2017年10月19日 第十次总结

热门文章

  1. FairFuzz 论文简读+源码分析+整体流程简述
  2. input框的一系列操作(输入框必填*号,验证单选框为必选,默认选中单选按钮,点击禁用表单输入域,输入框变为只读)
  3. dvd-rom属于什么
  4. LENOVO ERAZER Z51 安装固态指南
  5. Python_Task01:变量、运算符、数据类型及位运算
  6. 压力传感器中英文术语对照表
  7. 邻居好说话——冒泡排序
  8. 现代战争的制胜法宝?-黑科技原子无线电技术应用前景及最新研究进展
  9. 2020-11-22 Vue-10组件化开发(1)
  10. 计算机网络基础中国石油大学,2017中国石油大学继续教育计算机网络基础答案...