实现功能:计算带有括号和四则运算的式子   3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)

基本思路:使用正则表达式提取出每一层小括号式子,计算出结果后替换该括号,直至最后一层。

0、计算前的准备,进行式子的整理,如果非法则退出。这里我只对空格和符号进行了处理,真实场景中应该做更多的判断:

def check(s):
s = s.replace(" ", '')
s = re.sub(r'(\+-)|(-\+)', '-', s)
s = re.sub(r'(\+\+)|(--)', '+', s)
return s

1、只有加减运算的式子:findall匹配后直接使用sum函数对list求和,此时的减号看作负号,加号看作了正号,所以代码极其简洁:

import re

def plus_all(s): #实现加减运算
patter_plus = r'[+-]?\d+\.?\d*'
ret = re.findall(patter_plus, s)
return sum([float(x) for x in ret])

2、只有乘除运算的式子:和以上思路一致,主要想把除法(/)转换为乘法后用reduce计算。其先匹配出带有乘除运算符的list,然后通过change_mul_div()函数将除法转换成倒数计算

from functools import reduce

def mul_all(s):
patter_mul = r'[*/]?[-]?\d+\.?\d*'
ret = re.findall(patter_mul, s)
return reduce(lambda m, n: m*n, [change_mul_div(x) for x in ret]) def change_mul_div(s):
if "/" in s:
return 1 / float(s.replace('/', ""))
else:
return float(s.replace("*", ''))

3、含有加减乘除但不含有括号的式子:先用mul_all(s)函数将式子中的所有乘除法计算完毕,然后回到第1步。cal_all_mul_div函数实现计算式子中所有乘除法:

def cal_all_mul_div(s):
patter_all_mul_div = r'([+-]?\d+\.?\d*[*/])+[+-]?\d+\.?\d*'
ret = re.search(patter_all_mul_div, s)
while ret:
mul_div = mul_all(ret.group())
s = s.replace(ret.group(), ''.join(['+', str(mul_div)]))
ret = re.search(patter_all_mul_div, s)
return s

4、不断提取括号进行计算:

def bracket(s):
patter_kuohao = r'\([^()]+\)'
ret = re.search(patter_kuohao, s)
while ret:
cal_result = plus_all(cal_all_mul_div(ret.group()))
s=s.replace(ret.group(), ''.join(['+', str(cal_result)]))
ret = re.search(patter_kuohao, s)
return s

所有代码合并如下:

import re
from functools import reduce s3 = "3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)" def check(s):
s = s.replace(" ", '') #对空格进行处理
s = re.sub(r'(\+-)|(-\+)', '-', s) #对符号进行处理
s = re.sub(r'(\+\+)|(--)', '+', s)
return s def plus_all(s):
patter_plus = r'[+-]?\d+\.?\d*'
ret = re.findall(patter_plus, s) #找出所有的加数
return sum([float(x) for x in ret]) #生成器生成列表并求和 def mul_all(s):
patter_mul = r'[*/]?[-+]?\d+\.?\d*'
ret = re.findall(patter_mul, s)
return reduce(lambda m, n: m * n, [change_mul_div(x) for x in ret]) #reduce连乘 def change_mul_div(s): #把除法改成乘以其倒数
if "/" in s:
return 1 / float(s.replace('/', ""))
else:
return float(s.replace("*", '')) def cal_all_mul_div(s):
patter_all_mul_div = r'([+-]?\d+\.?\d*[*/])+[+-]?\d+\.?\d*'
ret = re.search(patter_all_mul_div, s)
while ret:
mul_div = mul_all(ret.group())
s = s.replace(ret.group(), ''.join(['+', str(mul_div)]))
ret = re.search(patter_all_mul_div, s)
return s def bracket(s):
patter_kuohao = r'\([^()]+\)'
s = check(s)
ret = re.search(patter_kuohao, s)
while ret:
cal_result = plus_all(cal_all_mul_div(ret.group()))
s = check(s.replace(ret.group(), ''.join(['+', str(cal_result)]))) #替换时需要在前面加入正号,并对s进行check操作
ret = re.search(patter_kuohao, s)
return s s3 = ''.join(["(", s3, ")"])
print(float(bracket(s3)))

以上即用不超过50行代码实现了计算器的主要功能。

50行代码实现python计算器主要功能的更多相关文章

  1. python爬虫实战:利用scrapy,短短50行代码下载整站短视频

    近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法.这忙我得帮,少不得就抓包分析了一下这个app,找到了视频的下载链接,帮他解决了这个小问题 ...

  2. 50行代码实现缓存,JAVA内存模型原理

    遇见这样的高人怎么办??下面是一个简单缓存的实现,相当牛叉!自己看吧,只有50行代码. 摘自:http://www.oschina.net/code/snippet_55577_3887 import ...

  3. HTML5游戏实战(1):50行代码实现正面跑酷游戏

    前段时间看到一个"熊来了"的HTML5跑酷游戏,它是一个典型的正面2D跑酷游戏,这里借用它来介绍一下用Gamebuilder+CanTK开发正面跑酷游戏的基本方法. CanTK(C ...

  4. 50行代码实现GAN | 干货演练

    2014年,Ian Goodfellow和他的同事发表了一篇论文,向世界介绍了生成对抗网络(GAN).通过对计算图和博弈论的创新性组合,他们表明如果有足够的建模能力,两个相互对抗的模型可以通过普通的反 ...

  5. 使用PyQt(Python+Qt)+动态编译36行代码实现的计算器

    PyQt是基于跨平台的图形界面C++开发工具Qt加Python包装的一个GPL软件(GPL是GNU General Public License的缩写,是GNU通用公共授权非正式的中文翻译),Qt基于 ...

  6. 基于requirejs+bluebird,50行代码实现轻巧实用的前端CMD加载器

    首先是github地址,可以用git克隆命令也可以直接在git页面下载 https://github.com/kazetotori/js-requireAsync 下载下来后目录结构是这样的 -pac ...

  7. [Lua]50行代码的解释器,用来演示lambda calculus

    嗯,来写写经过: 在知乎上看见用Belleve牛用javascript写了一个精简的lisp解释器 => 我也想写一个,用lua写,能多简单呢? => 写了一个阉割的scheme解释器,包 ...

  8. python学习---50行代码实现图片转字符画1

    转自:https://blog.csdn.net/mm1030533738/article/details/78447714 项目链接: https://www.shiyanlou.com/cours ...

  9. python学习---50行代码实现图片转字符画2

    from PIL import Image codeLib = '''@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<> ...

随机推荐

  1. python中descriptor的应用

    [python中descriptor的应用] 1.classmethod. 1)classmethod的应用. 2)classmethod原理. 2.staticmethod. 1)staticmet ...

  2. Eclipse下使用Subversion(SVN工具)

    本文目的 让未使用过版本控制器软件或者未使用过subversion软件的人员尽快上手. subversion的使用技巧很多,这里只总结了最小使用集,即主要的基本功能,能够用来应付日常工作. 因此不涉及 ...

  3. 【HDU6026】Deleting Edges

    题意 有一个n个节点的无向图,结点编号从0-n-1,每条边的长度时1to9的一个正整数.现在要删除一些边(或者不删),使得到的新图满足下面两个要求. 1.新图是一颗树有n-1条边2.对于每个结点v(0 ...

  4. 公共技术点之 Java 反射 Reflection

    本文摘录地址: http://codekk.com/open-source-project-analysis/detail/Android/Mr.Simple/%E5%85%AC%E5%85%B1%E ...

  5. Cannot connect to the Docker datemon at tcp://0.0.0.0:2375 is the docker daemon runing?

    一.系统环境: 在Windows 7 64位上,采用Vmware workstation 12安装了CenOS7.5 64位. 二.问题 在CentOS7.5里安装了Docker,启动docker服务 ...

  6. Makefile 编写规则 - 1

    Makefilen内容 1. 显示规则:显示规则说明了,如何生成一个或多个目标.这是由Makefile指出要生成的文件和文件依赖的文件.2. 隐晦规则:基于Makefile的自动推导功能3. 变量的定 ...

  7. ssh试卷

    2.简述Hibernate的工作原理. 答:首先,Configuration读取Hibernate的配置文件及映射文件中的信息,即加载配置文件和映射文件,并通过Hibernate配置文件生成一个多线程 ...

  8. nmap 笔记

    本文由阿德马翻译自国外网站,请尊重劳动成果,转载请注明出处,谢谢 1.初级用法: 教程   Nmap使用不同的技术来执行扫描,包括:TCP的connect()扫描,TCP反向的ident扫描,FTP反 ...

  9. 编写高质量代码改善C#程序的157个建议——建议8: 避免给枚举类型的元素提供显式的值

    建议8: 避免给枚举类型的元素提供显式的值 一般情况下,没有必要给枚举类型的元素提供显式的值.创建枚举的理由之一,就是为了代替使用实际的数值.不正确地为枚举类型的元素设定显式的值,会带来意想不到的错误 ...

  10. 20169219 实验一 Java开发环境的熟悉(Linux + IDEA)

    实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA 编辑.编译.运行.调试Java程序. 如条件断点设置:我们在第14行左边断点处单击鼠标右键,弹出断点属性框,我们设置条件&qu ...