需求

可以处理带括号的加减乘除运算

需求分析

匹配括号

re.search('\(.*\)',a)

匹配最里面括号

re.search(r'\([^()]+\)')

可以用strip()方法去掉括号

计算公式

1.0-2.0((60.0-30.0+(-40.0/5.0)(9.0-2.05.0/3.0+7.0/3.099.0/4.02998.0+10.0568.0/14.0)))

匹配二级括号

re.search('\(\(.*\)\)',a)

确定以上方法之后我们先来画流程图

calculator

实现

可以看到我们的逻辑是用re.findall(r'\([^()]+\)')判断是否存在括号,如果存在,我们就进入处理([^()]+)最里面括号的内容

这是一个循环,直到处理的没有([^()]+)这一项,也就代表没有括号内的内容了

如果一开始就没有匹配到([^()]+),那我们就直接按加减乘除的规则处理他

一开始的循环可以这么写:

loop_flag2=True

while loop_flag2:

if re.findall('\([^()]+\)',enter):

enter=three_level_brackets_func(enter)

else:

loop_flag2=False

else:

finnal_result=no_brackets_func(enter)

print(finnal_result)

然后按着流程图,先处理高级运算符,也就是乘法和除法运算符,我们先处理除法,这是因为在实际操作中,除法必须按从左到右的顺序运算,除法运算符先算左边的和先算右边的结果,是天差地别的变化,乘法还好,先乘左边的还是先乘右边的结果都是一样,请看下面的列子:

>>> 3/4/5

0.15

>>> 3/(4/5)

3.75

#乘法

>>> 3*4*5

60

>>> 3*(4*5)

60

除法这部分的逻辑如下:

while True:

if operation.find('/') != -1:

division_cal=re.search('[0-9]+.[0-9]+/[\+\-]?[0-9]+.[0-9]+',operation).group()

num1=re.findall('([0-9]+.[0-9]+)/',operation)

num2=re.findall('/([\+\-]?[0-9]+.[0-9]+)',operation)

print('division left:',num1)

print('division right:',num2)

num1=float(num1[0])

num2=float(num2[0])

division_result=num1/num2

print('division result:',division_result)

operation=operation.replace(division_cal,str(division_result))

print('now operation is:',operation)

如果我们发现运算行里有'/'这个符号,代表除法,那么我们就把运算行第一个除法公式提取出来,用division_cal=re.search('[0-9]+.[0-9]+/[\+\-]?[0-9]+.[0-9]+',operation).group(),匹配出来的是[0-9]+.[0-9]+/[+-]?[0-9]+.[0-9]+,就是两个有小数点的数字中间是 / 除法运算符,例如34.5/-55.6这种。

然后把除法运算符左边的数字拿出来num1=re.findall('([0-9]+.[0-9]+)/',operation),是一个列表,会把所有'/'左边的数字拿出来

再把除法运算符右边的数字拿出来num2=re.findall('/([\+\-]?[0-9]+.[0-9]+)',operation),同理也是一个列表

num1=float(num1[0]) num2=float(num2[0])

我们算两个列表里第一位的数字,因为两个列表里项目是一一匹配的(如果输入的运算式正确的话),两个列表的第一位就代表他们是这个运算行第一个除法运算

算出的结果,用这个结果替换第一个除法公式 operation=operation.replace(division_cal,str(division_result))

这个运算行就少了一个除法公式

再循环,直到没有任何除法公式

接着,我们把没有除法公式了的运算行输入乘法函数里处理。目的是把所有乘法公式也替换掉

逻辑如下:

elif operation.find('*') != -1:

mutlip_cal=re.search('[0-9]+.[0-9]+\*[\+\-]?[0-9]+.[0-9]+',operation).group()

num1=re.findall('([0-9]+.[0-9]+)\*',operation)

num2=re.findall('\*([\+\-]?[0-9]+.[0-9]+)',operation)

print('multiplication left:',num1)

print('multiplication right:',num2)

num1=float(num1[0])

num2=float(num2[0])

mutlip_result=num1*num2

print('multiplication result:',mutlip_result)

operation=operation.replace(mutlip_cal,str(mutlip_result))

print('now operation is:',operation)

跟除法的规则一样,先找到第一个乘法公式,然后提取乘法符号'*'左边和右边的数字,相乘出结果,替换公式,再循环,直到没有任何乘法

如果乘法和除法的处理都做完了,那接下去可以想象,就只剩下加减了

while loop_flag:

new_operation=operation.strip('()')

if len(re.split('[+-]',new_operation)) > 1 and re.split('[+-]',new_operation)[0]:

pri_cal=re.search('[\+\-]?[0-9]+.[0-9]+[\+\-][0-9]+.[0-9]+',new_operation).group()

num1=re.findall('([\+\-]?[0-9]+.[0-9]+)[\+\-]',pri_cal)

num2=re.findall('[\+\-]?[0-9]+.[0-9]+([\+\-][0-9]+.[0-9]+)',pri_cal)

num1=float(num1[0])

num2=float(num2[0])

pri_result=num1+num2

operation=operation.replace(pri_cal,str(pri_result))

print('now operation is:',operation)

之前的运算可能还留下括号没有处理,我们用new_operation=operation.strip('()')这一句来去掉左右括号

if len(re.split('[+-]',new_operation)) > 1

这是判断除了'+-'号之外,还有几项数字,如果大于1,那就是还需要运算,当然这样就有个漏洞,如果是'-34.5'这种数字,re.split('[+-]','-34.5')这种方法分裂出来的项目是[],[34.5] 这样也是大于1项的,所以我们加一句

if re.split('[+-]',new_operation)[0]:

来判断分裂出来的第一位是不是空

接下来,pri_cal=re.search('[\+\-]?[0-9]+.[0-9]+[\+\-][0-9]+.[0-9]+',new_operation).group() 提取出第一个加减运算公式

num1=re.findall('([\+\-]?[0-9]+.[0-9]+)[\+\-]',pri_cal) 提取左边的数字

num2=re.findall('[\+\-]?[0-9]+.[0-9]+([\+\-][0-9]+.[0-9]+)',pri_cal 提取右边的数字

运算,因为我们匹配右边数字的时候已经把加减号也匹配进去了,python是支持1+-1这样运算的,所以我们运算直接就是把两个值加一起

operation=operation.replace(pri_cal,str(pri_result)) 拿运算结果替换加减运算式

循环

这里可能会遇到这么几种情况,一个是,经过一轮处理之后 34-(-5*11) 这种变成了34--55这种公式,到我们加减处理的逻辑里就无法匹配了,还有34+-55,34--55这种情况出现,[+-]?[0-9]+.[0-9]+([+-][0-9]+.[0-9]+匹配里也没有,当然我们也可以中间的[+-]写成[+-]{1,2}这种匹配一到两次的,但是接下去的运算可不能成功算出34+--55的结果,所以单独做个函数把这些不合法的运算符处理下

def symbol_judge(enter):

if '+-' in enter:

enter=enter.replace('+-','-')

elif '-+' in enter:

enter=enter.replace('-+','-')

elif '--' in enter:

enter=enter.replace('--','+')

return enter

完善一下之前的循环

def process(enter,re_result):

for i in re_result:

pre_symbol_result=pre_symbol_cal(i)

pri_symbol_result=pri_symbol_cal(pre_symbol_result)

pri_symbol_result=pri_symbol_result.strip('()')

enter=enter.replace(i,pri_symbol_result)

return enter

def three_level_brackets_func(enter):

re_result=re.findall(r'\([^()]+\)',enter)

print('brackets inner:',re_result)

enter=process(enter,re_result)

enter=symbol_judge(enter)

print(enter)

return enter

loop_flag2=True

while loop_flag2:

if re.findall('\([^()]+\)',enter):

enter=three_level_brackets_func(enter)

else:

loop_flag2=False

else:

finnal_result=no_brackets_func(enter)

print(finnal_result)

先处理括号内的内容,按照先乘除,再加减,结果去除左右括号,替换运算行里的(^[]+)内容,最后再对运算行里的不合法符号做个判断,传给开始的循环,再走一轮

终于我们的运算式里没有了括号,接着就该直接按先乘除后加减的四则运算逻辑,处理它们了

def no_brackets_func(enter):

print('HIT no_brackets')

if enter[0] == '-':

enter='0'+enter

raw_enter=pre_symbol_cal(enter)

raw_enter=symbol_judge(raw_enter)

enter=pri_symbol_cal(raw_enter)

print(enter)

return enter

这里面有个小细节,如果运算式开头是-34/55+66...这样子的,咱们之前写的逻辑就要再改了,好多地方也要调整,为了方便复用之前的代码,也是偷懒,其实只用在'-'号前面加一个0即可,逻辑走得通,同时不影响结果

好了,完整的代码如下:

#-*- coding:utf-8 -*-

#owner:houyizhong

import re

print('输入数字必须保留小数点一位\n例子:1.0-2.0*((60.0-30.0+(-40.0/5.0)*(9.0-2.0*5.0/3.0+7.0/3.0*99.0/4.0*2998.0+10.0*568.0/14.0))+(65.0+77.0)+6.0)')

enter=input('>>>')

def pre_symbol_cal(operation):

loop_flag=True

while loop_flag:

if operation.find('/') != -1:

division_cal=re.search('[0-9]+.[0-9]+/[\+\-]?[0-9]+.[0-9]+',operation).group()

num1=re.findall('([0-9]+.[0-9]+)/',operation)

num2=re.findall('/([\+\-]?[0-9]+.[0-9]+)',operation)

print('division left:',num1)

print('division right:',num2)

num1=float(num1[0])

num2=float(num2[0])

division_result=num1/num2

print('division result:',division_result)

operation=operation.replace(division_cal,str(division_result))

print('now operation is:',operation)

elif operation.find('*') != -1:

mutlip_cal=re.search('[0-9]+.[0-9]+\*[\+\-]?[0-9]+.[0-9]+',operation).group()

num1=re.findall('([0-9]+.[0-9]+)\*',operation)

num2=re.findall('\*([\+\-]?[0-9]+.[0-9]+)',operation)

print('multiplication left:',num1)

print('multiplication right:',num2)

num1=float(num1[0])

num2=float(num2[0])

mutlip_result=num1*num2

print('multiplication result:',mutlip_result)

operation=operation.replace(mutlip_cal,str(mutlip_result))

print('now operation is:',operation)

else:

loop_flag=False

return operation

def pri_symbol_cal(operation):

loop_flag=True

while loop_flag:

new_operation=operation.strip('()')

if len(re.split('[+-]',new_operation)) > 1 and re.split('[+-]',new_operation)[0]:

pri_cal=re.search('[\+\-]?[0-9]+.[0-9]+[\+\-][0-9]+.[0-9]+',new_operation).group()

num1=re.findall('([\+\-]?[0-9]+.[0-9]+)[\+\-]',pri_cal)

num2=re.findall('[\+\-]?[0-9]+.[0-9]+([\+\-][0-9]+.[0-9]+)',pri_cal)

num1=float(num1[0])

num2=float(num2[0])

pri_result=num1+num2

operation=operation.replace(pri_cal,str(pri_result))

print('now operation is:',operation)

else:

loop_flag=False

return operation

def symbol_judge(enter):

if '+-' in enter:

enter=enter.replace('+-','-')

elif '-+' in enter:

enter=enter.replace('-+','-')

elif '--' in enter:

enter=enter.replace('--','+')

return enter

def process(enter,re_result):

for i in re_result:

pre_symbol_result=pre_symbol_cal(i)

pri_symbol_result=pri_symbol_cal(pre_symbol_result)

pri_symbol_result=pri_symbol_result.strip('()')

enter=enter.replace(i,pri_symbol_result)

return enter

def three_level_brackets_func(enter):

re_result=re.findall(r'\([^()]+\)',enter)

print('brackets inner:',re_result)

enter=process(enter,re_result)

enter=symbol_judge(enter)

print(enter)

return enter

def no_brackets_func(enter):

print('HIT no_brackets')

if enter[0] == '-':

enter='0'+enter

raw_enter=pre_symbol_cal(enter)

raw_enter=symbol_judge(raw_enter)

enter=pri_symbol_cal(raw_enter)

print(enter)

return enter

loop_flag2=True

while loop_flag2:

if re.findall('\([^()]+\)',enter):

enter=three_level_brackets_func(enter)

else:

loop_flag2=False

else:

finnal_result=no_brackets_func(enter)

print(finnal_result)

python之路day5_学习python之路--Day5 计算器相关推荐

  1. 学python语言用什么软件-Python是什么?学习Python用什么编译器?

    原标题:Python是什么?学习Python用什么编译器? Python是一个非常好用的程序语言,开发的速度非常快.Python的设计哲学是优雅.明确.简单.因此,Perl语言中总是有多种方法来做同一 ...

  2. python新手教程 从零开始-Python零基础从零开始学习Python十分钟快速入门

    原标题:Python零基础从零开始学习Python十分钟快速入门 学习Python的,都知道Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.Python是一种动态解释型的 ...

  3. 初学者先学python语音好吗_献给Python初学者 零基础学习Python能学会吗

    献给Python初学者 零基础学习Python能学会吗 时间:2018-01-08     来源:零基础学习Python方法讲解 零基础学习Python能学会吗?这个问题几乎是所有初学Python的小 ...

  4. 学python多贵_老男孩学习Python多少钱,学习Python贵吗?

    而且现在不少人都想要参加python培训,在进行python培训之前,大家最关注的的莫过于培训机构好不好的问题了,当然了收费也是我们需要考虑的一点.当然选择培训机构不能只看费用方面的,还需要考虑师资力 ...

  5. 自学python需要的软件-学习Python,从入门到精通,其实只需要两个月就够了

    毫无疑问,Python 是当下最火的编程语言之一.对于许多未曾涉足计算机编程的领域「小白」来说,深入地掌握 Python 看似是一件十分困难的事.其实,只要掌握了科学的学习方法并制定了合理的学习计划, ...

  6. python自学教程推荐-学习python中的pandas有没有好的教程推荐?

    上来就丢教程和资料,其实是把路带偏了!找到学习Pandas的方法比找教程重要的多!现在无论是学习Python还是Pandas,最大的问题不是没有资料,而恰恰是太多资料和教程,让人抓不住头绪. 很多凭着 ...

  7. 学习python需要什么基础-学习python需要什么基础

    Python编程基础知识的学习最终目的是应用于项目中,因此,项目实战训练必不可少.下面小编给大家介绍学习python需要什么基础,一起来看看吧. 学习python需要掌握的基础 1.要有决心 做任何事 ...

  8. 初学者怎么自学python编程_怎样自学python编程?从零开始学习python,400集免费教程!...

    作为小白,在学习Python的时候,必然会走一定的弯路,有人在弯路上走丢了,有人走出了弯路.我就是属于还未走出弯路的同学,所以我想谈谈我的Python学习之路. 01先了解一下什么是python‍? ...

  9. python作品代码_学习python的一些心得体会

    初识python 专升本来到桂林电子科技大学的时候,谈及这个学校也许他是全国四所叫电子科技大学的学校,而我很幸运的从这个学校里毕业了,那个时候选修一门课程就是python的选修课,从此跟python结 ...

最新文章

  1. 我在 Spring 的 BeanUtils 踩到的那些坑,千万不要犯!
  2. Matlab入门笔记
  3. 程序员应该知道的七个图形工具
  4. python自建包的根目录可以直接import的方法
  5. FPL 2017最佳论文:如何对FPGA云发动DoS攻击?
  6. 1^2+2^2+……+n^2的公式证明
  7. html 图片防盗链,【反防盗链】介绍一个对付图片防盗链的方法
  8. php显示控制器不存在,解决ThinkPHP6提示控制器不存在问题
  9. VIM插件管理:管理插件的插件pathogen
  10. 惊!揭秘AI人工智能机器人自动写诗的奥秘!
  11. MP3 功能原理 及 软件方案设计(一)
  12. 重磅!2021年国内有名的编程培训机构排名公布啦
  13. 停止等待协议与连续 ARQ 协议
  14. Java微服务+分布式+全栈项目(一)---->项目介绍+MyBatis-Plus入门
  15. kubernetes 与 rook 架构说明
  16. 项目策划 文件管理系统
  17. 计算机基础:今天一次把 Unicode 和 UTF-8 说清楚
  18. GUI编程--PyQt5--QWidget2
  19. Python GUI编程 --转发:https://www.jianshu.com/p/91844c5bca78?tdsourcetag=s_pcqq_aiomsg
  20. J2EE金融项目开发实战视频教程

热门文章

  1. goland配置mysql失败_GoLand配置数据库、远程host以及远程调试
  2. Java多线程详解(线程池)
  3. c mysql linux,linux上C语言连接mysql
  4. mie散射理论方程_散射,原子分子散射
  5. mariadb不支持load data_不修改代码打包python机器学习工程
  6. SQL Server 2014安装图解
  7. 这是一台家庭计算机重启无效,我买了一台二手计算机,配置还可以,但有时会自动重启机器,这是为什? 爱问知识人...
  8. 企业云成本浪费高达30%!行云管家、Cloudyn等厂商给出解决方案...
  9. 澳大利亚超市巨头考虑设专门网站 方便代购买奶粉
  10. 默认conf指向位置