作业:

使用正则表达式和递归实现计算器功能。

实现:

1、实现带括号的计算

2、实现指数、加减乘除求余等功能

一、实例说明:

本实例自己写了个版本,但依旧存在一点bug,例:-2-2等计算问题,故最后在武SIR的代码基础上加了指数、求余等功能。

该计算器思路:
1、递归寻找表达式中只含有 数字和运算符的表达式,并计算结果
2、由于整数计算会忽略小数,所有的数字都认为是浮点型操作,以此来保留小数
使用技术:
1、正则表达式
2、递归

二、流程图:

三、代码:

  1. #!/usr/bin/python27
  2. #_*_ coding=utf-8 _*_
  3.  
  4. '''
  5. Created on 2016年1月17日
  6. @author: 王凯
  7. '''
  8.  
  9. '''
  10. 该计算器思路:
  11. 1、递归寻找表达式中只含有 数字和运算符的表达式,并计算结果
  12. 2、由于整数计算会忽略小数,所有的数字都认为是浮点型操作,以此来保留小数
  13. 使用技术:
  14. 1、正则表达式
  15. 2、递归
  16.  
  17. 执行流程如下:
  18. ******************** 请计算表达式: 1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ********************
  19. 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))']
  20. -40.0/5=-8.0
  21. after: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
  22. ========== 上一次计算结束 ==========
  23. before: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
  24. 9-2*5/3+7/3*99/4*2998+10*568/14=173545.880953
  25. after: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
  26. ========== 上一次计算结束 ==========
  27. before: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
  28. 60-30+-8.0*173545.880953=-1388337.04762
  29. after: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
  30. ========== 上一次计算结束 ==========
  31. before: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
  32. -4*3=-12.0
  33. after: ['1-2*(-1388337.04762--12.0/(16-3*2))']
  34. ========== 上一次计算结束 ==========
  35. before: ['1-2*(-1388337.04762--12.0/(16-3*2))']
  36. 16-3*2=10.0
  37. after: ['1-2*(-1388337.04762--12.0/10.0)']
  38. ========== 上一次计算结束 ==========
  39. before: ['1-2*(-1388337.04762--12.0/10.0)']
  40. -1388337.04762--12.0/10.0=-1388335.84762
  41. after: ['1-2*-1388335.84762']
  42. ========== 上一次计算结束 ==========
  43. 我的计算结果: 2776672.69524
  44. '''
  45.  
  46. import re,os,sys
  47.  
  48. def compute_exponent(arg):
  49. """ 操作指数
  50. :param expression:表达式
  51. :return:计算结果
  52. """
  53.  
  54. val = arg[0]
  55. pattern = re.compile(r'\d+\.?\d*[\*]{2}[\+\-]?\d+\.?\d*')
  56. mch = pattern.search(val)
  57. if not mch:
  58. return
  59. content = pattern.search(val).group()
  60.  
  61. if len(content.split('**'))>1:
  62. n1, n2 = content.split('**')
  63. value = float(n1) ** float(n2)
  64. else:
  65. pass
  66.  
  67. before, after = pattern.split(val, 1)
  68. new_str = "%s%s%s" % (before,value,after)
  69. arg[0] = new_str
  70. compute_exponent(arg)
  71.  
  72. def compute_mul_div(arg):
  73. """ 操作乘除
  74. :param expression:表达式
  75. :return:计算结果
  76. """
  77.  
  78. val = arg[0]
  79. pattern = re.compile(r'\d+\.?\d*[\*\/\%\/\/]+[\+\-]?\d+\.*\d*')
  80. mch = pattern.search(val)
  81. if not mch:
  82. return
  83. content = pattern.search(val).group()
  84.  
  85. if len(content.split('*'))>1:
  86. n1, n2 = content.split('*')
  87. value = float(n1) * float(n2)
  88. elif len(content.split('//'))>1:
  89. n1, n2 = content.split('//')
  90. value = float(n1) // float(n2)
  91. elif len(content.split('%'))>1:
  92. n1, n2 = content.split('%')
  93. value = float(n1) % float(n2)
  94. elif len(content.split('/'))>1:
  95. n1, n2 = content.split('/')
  96. value = float(n1) / float(n2)
  97. else:
  98. pass
  99.  
  100. before, after = pattern.split(val, 1)
  101. new_str = "%s%s%s" % (before,value,after)
  102. arg[0] = new_str
  103. compute_mul_div(arg)
  104.  
  105. def compute_add_sub(arg):
  106. """ 操作加减
  107. :param expression:表达式
  108. :return:计算结果
  109. """
  110. while True:
  111. if arg[0].__contains__('+-') or arg[0].__contains__("++") or arg[0].__contains__('-+') or arg[0].__contains__("--"):
  112. arg[0] = arg[0].replace('+-','-')
  113. arg[0] = arg[0].replace('++','+')
  114. arg[0] = arg[0].replace('-+','-')
  115. arg[0] = arg[0].replace('--','+')
  116. else:
  117. break
  118.  
  119. if arg[0].startswith('-'):
  120.  
  121. arg[1] += 1
  122. arg[0] = arg[0].replace('-','&')
  123. arg[0] = arg[0].replace('+','-')
  124. arg[0] = arg[0].replace('&','+')
  125. arg[0] = arg[0][1:]
  126. val = arg[0]
  127.  
  128. pattern = re.compile(r'\d+\.?\d*[\+\-]{1}\d+\.?\d*')
  129. mch = pattern.search(val)
  130. if not mch:
  131. return
  132. content = pattern.search(val).group()
  133. if len(content.split('+'))>1:
  134. n1, n2 = content.split('+')
  135. value = float(n1) + float(n2)
  136. else:
  137. n1, n2 = content.split('-')
  138. value = float(n1) - float(n2)
  139.  
  140. before, after = pattern.split(val, 1)
  141. new_str = "%s%s%s" % (before,value,after)
  142. arg[0] = new_str
  143. compute_add_sub(arg)
  144.  
  145. def compute(expression):
  146. """ 操作加减乘除
  147. :param expression:表达式
  148. :return:计算结果
  149. """
  150. inp = [expression,0]
  151.  
  152. # 处理表达式中的指数
  153. compute_exponent(inp)
  154.  
  155. # 处理表达式中的乘除求余等
  156. compute_mul_div(inp)
  157.  
  158. # 处理表达式的加减
  159. compute_add_sub(inp)
  160. if divmod(inp[1],2)[1] == 1:
  161. result = float(inp[0])
  162. result = result * -1
  163. else:
  164. result = float(inp[0])
  165. return result
  166.  
  167. def exec_bracket(expression):
  168. """ 递归处理括号,并计算
  169. :param expression: 表达式
  170. :return:最终计算结果
  171. """
  172. pattern = re.compile(r'\(([\+\-\*\/\%\/\/\*\*]*\d+\.*\d*){2,}\)')
  173. # 如果表达式中已经没有括号,则直接调用负责计算的函数,将表达式结果返回,如:2*1-82+444
  174. #if not re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression):
  175. if not pattern.search(expression):
  176. final = compute(expression)
  177. return final
  178. # 获取 第一个 只含有 数字/小数 和 操作符 的括号
  179. # 如:
  180. # ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
  181. # 找出:(-40.0/5)
  182. content = pattern.search(expression).group()
  183.  
  184. # 分割表达式,即:
  185. # 将['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
  186. # 分割更三部分:['1-2*((60-30+( (-40.0/5) *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
  187. before, nothing, after = pattern.split(expression, 1)
  188.  
  189. print('before:',expression)
  190. content = content[1:len(content)-1]
  191.  
  192. # 计算,提取的表示 (-40.0/5),并活的结果,即:-40.0/5=-8.0
  193. ret = compute(content)
  194.  
  195. print('%s=%s' %( content, ret))
  196.  
  197. # 将执行结果拼接,['1-2*((60-30+( -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
  198. expression = "%s%s%s" %(before, ret, after)
  199. print('after:',expression)
  200. print("="*10,'previous result is',"="*10)
  201.  
  202. # 循环继续下次括号处理操作,本次携带者的是已被处理后的表达式,即:
  203. # ['1-2*((60-30+ -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
  204.  
  205. # 如此周而复始的操作,直到表达式中不再含有括号
  206. return exec_bracket(expression)
  207.  
  208. # 使用 __name__ 的目的:
  209. # 只有执行 python index.py 时,以下代码才执行
  210. # 如果其他人导入该模块,以下代码不执行
  211. if __name__ == "__main__":
  212. flag = True
  213.  
  214. os.system('clear') ###清屏###
  215.  
  216. print('\n================================================================')
  217. print('\033[33m 欢迎使用计算器 :\033[0m')
  218. print('\n================================================================')
  219.  
  220. while flag:
  221. calculate_input = raw_input('\033[32m请输入计算的表达式 | (退出:q)\033[0m')
  222. calculate_input = re.sub('\s*','',calculate_input)
  223. if len(calculate_input) == 0:
  224. continue
  225. elif calculate_input == 'q':
  226. sys.exit('退出程序')
  227. elif re.search('[^0-9\.\-\+\*\/\%\/\/\*\*\(\)]',calculate_input):
  228. print('\033[31m 输入错误,请重新输入!!!\033[0m')
  229. else:
  230. result = exec_bracket(calculate_input)
  231. print('the expression result is %s' % result)

计算器

四、针对python2.7和python3.4无太大差别,故只需要一个版本即可。

python之计算器(第四天)的更多相关文章

  1. python学习心得第四章

     python 学习心得第四章 1.lambda表达式 1:什么是lambda表达式 为了简化简单函数的代码,选择使用lambda表达式 上面两个函数的表达式虽然不一样,但是本质是一样的,并且lamb ...

  2. 机器学习算法与Python实践之(四)支持向量机(SVM)实现

    机器学习算法与Python实践之(四)支持向量机(SVM)实现 机器学习算法与Python实践之(四)支持向量机(SVM)实现 zouxy09@qq.com http://blog.csdn.net/ ...

  3. Python爬虫学习:四、headers和data的获取

    之前在学习爬虫时,偶尔会遇到一些问题是有些网站需要登录后才能爬取内容,有的网站会识别是否是由浏览器发出的请求. 一.headers的获取 就以博客园的首页为例:http://www.cnblogs.c ...

  4. python机器学习实战(四)

    python机器学习实战(三) 版权声明:本文为博主原创文章,转载请指明转载地址 www.cnblogs.com/fydeblog/p/7364317.html 前言 这篇notebook是关于机器学 ...

  5. Python学习笔记(四)

    Python学习笔记(四) 作业讲解 编码和解码 1. 作业讲解 重复代码瘦身 # 定义地图 nav = {'省略'} # 现在所处的层 current_layer = nav # 记录你去过的地方 ...

  6. 《python参考手册(第四版)》【PDF】下载

    <python参考手册(第四版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382222 内容介绍 本书是权威的Python语 ...

  7. 从零开始学习PYTHON3讲义(二)把Python当做计算器

    <从零开始PYTHON3>第二讲 上一讲我们说过了如何启动Python IDLE集成开发学习环境,macOS/Linux都可以在命令行执行idle3.Windows则从开始菜单中去寻找ID ...

  8. Python遍历List集合四种方法

    这篇文章主要介绍了Python 列表(List) 的四种遍历方法实例 详解的相关资料,需要的朋友可以参考下 分别是:直接遍历对象 通过索引遍历 通过enumerate方法 通过iter方法. 使用Py ...

  9. 孤荷凌寒自学python第八十四天搭建jTessBoxEditor来训练tesseract模块

    孤荷凌寒自学python第八十四天搭建jTessBoxEditor来训练tesseract模块 (完整学习过程屏幕记录视频地址在文末) 由于本身tesseract模块针对普通的验证码图片的识别率并不高 ...

  10. Python学习系列(四)(列表及其函数)

    Python学习系列(四)(列表及其函数) Python学习系列(一)(基础入门) Python学习系列(二)(基础知识) Python学习系列(三)(字符串) 一.基本概念 1,列表是什么?     ...

随机推荐

  1. Java并发编程底层实现原理 - volatile

    Java语言规范第三版中对volatile的定义如下: Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致性的更新,线程应该确保通过排他锁 单独获得这个变量. volatile有时候 ...

  2. poj1753

    #include <stdio.h> char s[100][100]; int s1[100][100]; int ax[5]={0,-1,0,1,0}; int ay[5]={0,0, ...

  3. 在将 varchar 值 '' 转换成数据类型 int 时失败

    我们有时候用in语句的时候,发现存在Sql注入漏洞,想参数化处理一下,遇到语句执行问题!! declare @ids varchar() set @ids='216,218' select * fro ...

  4. zTree的内核

    zTree的内核:   *  结构       (function($){           //常量部分           //申明常量是因为这些数据是不能改变的,如果成了对象的属性,很容易就改 ...

  5. 学习Python的ABC模块(转)

    http://yansu.org/2013/06/09/learn-Python-abc-module.html 1.abc模块作用 Python本身不提供抽象类和接口机制,要想实现抽象类,可以借助a ...

  6. 使用jspatch进行热修复的实战总结

    最近正式在线上项目中集成了jspatch进行热修复,这里做一个简单的总结. 工具篇: 首先,用xcode来编辑js非常困难,基本上没有缩进,完全需要手写:经过研究发现使用 Sublime text3 ...

  7. js正则匹配的一个日常应用

    应用实例 1 /** 将段落中的 \n 转换为 <p></p>, 规范存储 */ 2 function formatParagraphForStore(val) { 3 var ...

  8. Ehcache Demo

    转自: https://my.oschina.net/zb0423/blog/60957http://www.cnblogs.com/fsjin/articles/3521261.html Ehcac ...

  9. HTML中head里的内容经浏览器解析后全到body里了

    HTML中head里的内容经浏览器解析后全到body里了 修改完代码后,用chrome审查元素,head里的内容都到body中去了 http://bbs.csdn.net/topics/3802586 ...

  10. 初识The Battle of Polytopia

    1.首先了解了一下<文明5-美丽新文明>视频介绍网址:http://list.youku.com/albumlist/show?id=19481409&ascending=1&am ...