python 编程之计算器
作业:
使用正则表达式和递归实现计算器功能。
实现:
1、实现带括号的计算
2、实现指数、加减乘除求余等功能
一、实例说明:
本实例自己写了个版本,但依旧存在一点bug,例:-2-2等计算问题,故最后在武SIR的代码基础上加了指数、求余等功能。
该计算器思路:
1、递归寻找表达式中只含有 数字和运算符的表达式,并计算结果
2、由于整数计算会忽略小数,所有的数字都认为是浮点型操作,以此来保留小数
使用技术:
1、正则表达式
2、递归
二、流程图:

三、代码:
#!/usr/bin/python27
#_*_ coding=utf-8 _*_ '''
''' '''
该计算器思路:
1、递归寻找表达式中只含有 数字和运算符的表达式,并计算结果
2、由于整数计算会忽略小数,所有的数字都认为是浮点型操作,以此来保留小数
使用技术:
1、正则表达式
2、递归 执行流程如下:
******************** 请计算表达式: 1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ********************
before: ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
-40.0/5=-8.0
after: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
========== 上一次计算结束 ==========
before: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
9-2*5/3+7/3*99/4*2998+10*568/14=173545.880953
after: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
========== 上一次计算结束 ==========
before: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
60-30+-8.0*173545.880953=-1388337.04762
after: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
========== 上一次计算结束 ==========
before: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
-4*3=-12.0
after: ['1-2*(-1388337.04762--12.0/(16-3*2))']
========== 上一次计算结束 ==========
before: ['1-2*(-1388337.04762--12.0/(16-3*2))']
16-3*2=10.0
after: ['1-2*(-1388337.04762--12.0/10.0)']
========== 上一次计算结束 ==========
before: ['1-2*(-1388337.04762--12.0/10.0)']
-1388337.04762--12.0/10.0=-1388335.84762
after: ['1-2*-1388335.84762']
========== 上一次计算结束 ==========
我的计算结果: 2776672.69524
''' import re,os,sys def compute_exponent(arg):
""" 操作指数
:param expression:表达式
:return:计算结果
""" val = arg[0]
pattern = re.compile(r'\d+\.?\d*[\*]{2}[\+\-]?\d+\.?\d*')
mch = pattern.search(val)
if not mch:
return
content = pattern.search(val).group() if len(content.split('**'))>1:
n1, n2 = content.split('**')
value = float(n1) ** float(n2)
else:
pass before, after = pattern.split(val, 1)
new_str = "%s%s%s" % (before,value,after)
arg[0] = new_str
compute_exponent(arg) def compute_mul_div(arg):
""" 操作乘除
:param expression:表达式
:return:计算结果
""" val = arg[0]
pattern = re.compile(r'\d+\.?\d*[\*\/\%\/\/]+[\+\-]?\d+\.*\d*')
mch = pattern.search(val)
if not mch:
return
content = pattern.search(val).group() if len(content.split('*'))>1:
n1, n2 = content.split('*')
value = float(n1) * float(n2)
elif len(content.split('//'))>1:
n1, n2 = content.split('//')
value = float(n1) // float(n2)
elif len(content.split('%'))>1:
n1, n2 = content.split('%')
value = float(n1) % float(n2)
elif len(content.split('/'))>1:
n1, n2 = content.split('/')
value = float(n1) / float(n2)
else:
pass before, after = pattern.split(val, 1)
new_str = "%s%s%s" % (before,value,after)
arg[0] = new_str
compute_mul_div(arg) def compute_add_sub(arg):
""" 操作加减
:param expression:表达式
:return:计算结果
"""
while True:
if arg[0].__contains__('+-') or arg[0].__contains__("++") or arg[0].__contains__('-+') or arg[0].__contains__("--"):
arg[0] = arg[0].replace('+-','-')
arg[0] = arg[0].replace('++','+')
arg[0] = arg[0].replace('-+','-')
arg[0] = arg[0].replace('--','+')
else:
break if arg[0].startswith('-'): arg[1] += 1
arg[0] = arg[0].replace('-','&')
arg[0] = arg[0].replace('+','-')
arg[0] = arg[0].replace('&','+')
arg[0] = arg[0][1:]
val = arg[0] pattern = re.compile(r'\d+\.?\d*[\+\-]{1}\d+\.?\d*')
mch = pattern.search(val)
if not mch:
return
content = pattern.search(val).group()
if len(content.split('+'))>1:
n1, n2 = content.split('+')
value = float(n1) + float(n2)
else:
n1, n2 = content.split('-')
value = float(n1) - float(n2) before, after = pattern.split(val, 1)
new_str = "%s%s%s" % (before,value,after)
arg[0] = new_str
compute_add_sub(arg) def compute(expression):
""" 操作加减乘除
:param expression:表达式
:return:计算结果
"""
inp = [expression,0] # 处理表达式中的指数
compute_exponent(inp) # 处理表达式中的乘除求余等
compute_mul_div(inp) # 处理表达式的加减
compute_add_sub(inp)
if divmod(inp[1],2)[1] == 1:
result = float(inp[0])
result = result * -1
else:
result = float(inp[0])
return result def exec_bracket(expression):
""" 递归处理括号,并计算
:param expression: 表达式
:return:最终计算结果
"""
pattern = re.compile(r'\(([\+\-\*\/\%\/\/\*\*]*\d+\.*\d*){2,}\)')
# 如果表达式中已经没有括号,则直接调用负责计算的函数,将表达式结果返回,如:2*1-82+444
#if not re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression):
if not pattern.search(expression):
final = compute(expression)
return final
# 获取 第一个 只含有 数字/小数 和 操作符 的括号
# 如:
# ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
# 找出:(-40.0/5)
content = pattern.search(expression).group() # 分割表达式,即:
# 将['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
# 分割更三部分:['1-2*((60-30+( (-40.0/5) *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
before, nothing, after = pattern.split(expression, 1) print('before:',expression)
content = content[1:len(content)-1] # 计算,提取的表示 (-40.0/5),并活的结果,即:-40.0/5=-8.0
ret = compute(content) print('%s=%s' %( content, ret)) # 将执行结果拼接,['1-2*((60-30+( -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
expression = "%s%s%s" %(before, ret, after)
print('after:',expression)
print("="*10,'previous result is',"="*10) # 循环继续下次括号处理操作,本次携带者的是已被处理后的表达式,即:
# ['1-2*((60-30+ -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] # 如此周而复始的操作,直到表达式中不再含有括号
return exec_bracket(expression) # 使用 __name__ 的目的:
# 只有执行 python index.py 时,以下代码才执行
# 如果其他人导入该模块,以下代码不执行
if __name__ == "__main__":
flag = True os.system('clear') ###清屏### print('\n================================================================')
print('\033[33m 欢迎使用计算器 :\033[0m')
print('\n================================================================') while flag:
calculate_input = raw_input('\033[32m请输入计算的表达式 | (退出:q)\033[0m')
calculate_input = re.sub('\s*','',calculate_input)
if len(calculate_input) == 0:
continue
elif calculate_input == 'q':
sys.exit('退出程序')
elif re.search('[^0-9\.\-\+\*\/\%\/\/\*\*\(\)]',calculate_input):
print('\033[31m 输入错误,请重新输入!!!\033[0m')
else:
result = exec_bracket(calculate_input)
print('the expression result is %s' % result)
四、针对python2.7和python3.4无太大差别,故只需要一个版本即可。
python 编程之计算器的更多相关文章
- jacky解读麻省理工《计算机科学与Python编程导论》第1集
文:@数据分析-jacky(朱元禄) (一)导言 本课程讲的中心思想就是五个字:计算机思维 Python只是辅助工具,是辅助大家理解计算机思维,仅此而已 急功近利是人性,适得其反是结果:我们看到有很多 ...
- Python黑帽编程2.1 Python编程哲学
Python黑帽编程2.1 Python编程哲学 本节的内容有些趣味性,涉及到很多人为什么会选择Python,为什么会喜欢这门语言.我带大家膜拜下Python作者的Python之禅,然后再来了解下P ...
- Linux运维人员如何学习python编程
Linux运维人员如何学习python编程 从不会写代码,到自己独立能写代码解决问题 .这个问题很重要!盲目学习所谓的项目,最后 还是不会自己写代码解决问题.首先解决了独立能写代码解决问题,再通过项目 ...
- Python编程核心之makeTextFile.py和readTextFile.py
引言: 最近大半年都在学习python编程,在双十一的时候购买了<Python编程核心>,看到makeTextFile.py和readTextFile.py两个例子有点错误,所以在这里给修 ...
- Python编程规范(PEP8)
Python编程规范(PEP8) 代码布局 缩进 对于每一次缩进使用4个空格.使用括号.中括号.大括号进行垂直对齐,或者缩进对齐. 制表符还是空格? 永远不要将制表符与空格混合使用.Python最常用 ...
- Python 编程规范-----转载
Python编程规范及性能优化 Ptyhon编程规范 编码 所有的 Python 脚本文件都应在文件头标上 # -*- coding:utf-8 -*- .设置编辑器,默认保存为 utf-8 格式. ...
- 学习Python编程的11个资源
用 Python 写代码并不难,事实上,它一直以来都是被声称为最容易学习的编程语言.如果你正打算学习 web 开发,Python 是一个不错的选择,甚至你想学游戏开发也可 以从 Python 开始,因 ...
- Emacs 配置 Python 编程环境
python编程环境设置涉及到:自动完成.语法检查.虚拟环境. 为了不把系统搞乱,在python的虚拟环境中安装相关的插件. 一.安装python虚拟环境 virtualenvwrapper sudo ...
- Python编程规范及性能优化(转载)
转载地址:http://codeweblog.com/python编程规范及性能优化/
随机推荐
- 2 storm的topology提交执行
本博文的主要内容有 .storm单机模式,打包,放到storm集群 .Storm的并发机制图 .Storm的相关概念 .附PPT 打包,放到storm集群去.我这里,是单机模式下的storm. wee ...
- The Doors - POJ 1556 (线段相交)
题目大意:有一个房间(左上角(0,10),右下角(10,0)),然后房间里有N面墙,每面墙上都有两个门,求出来从初始点(0,5),到达终点(10,5)的最短距离. 分析:很明显根据两点之间直线最短 ...
- 圣诞节来了,雪花纷飞的CSS3动画
原文链接:http://www.html5think.com/article/index/id/80
- JS方法在iframe父子窗口间的调用
本文向大家简单介绍一下iframe父子窗口间JS方法调用,JavaScript 被数百万计的网页用来改进设计.验证表单.检测浏览器.创建cookies,以及更多的应用,希望本文介绍对你有所帮助. if ...
- ASP.NET通过http/https的POST方式,发送和接受XML文件内容
本文转载:http://hi.baidu.com/ysyhyt/item/5011ae39ce3cf49fb80c0395 本文参考:http://blog.csdn.net/ououou123456 ...
- SQL字符串处理函数大全
select语句中只能使用sql函数对字段进行操作(链接sql server),select 字段1 from 表1 where 字段1.IndexOf("云")=1;这条语句不对 ...
- 内部开发环境 git代码托管说明
前言 随着员工的增加 代码的开发版本管理 提上了日程.初步计划: 1 一台机器 192.168.1.240 git代码版本管理 2 运行环境 192.168.1.241 内部开发运行环境 软件工程师 ...
- android 56
##其他布局 * LinearLayout * RelativeLayout * FrameLayout * AbsoluteLayout (绝对布局, 文档说过时,应用场景机顶盒开发,定制的平板) ...
- linux 最大文件描述符fd
使用四种框架分别实现百万websocket常连接的服务器 著名的 C10K 问题提出的时候, 正是 2001 年.这篇文章可以说是高性能服务器开发的一个标志性文档,它讨论的就是单机为1万个连接提供服务 ...
- [转] Bound Service的三种方式(Binder、 Messenger、 AIDL)
首先要明白需要的情景,然后对三种方式进行选择: (一)可以接收Service的信息(获取Service中的方法),但不可以给Service发送信息 (二) 使用Messenger既可以接受Servic ...