Python之实现简单计算器功能
一,需求分析
要求计算一串包含数字+-*/()的类似于3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)表达式的数值
二,知识点
- 正则表达式
- 元素切片
- 函数
- 函数递归
三,流程分析
- 判断字符串是否包含()如果有先处理()内表达式并且计算结果返回新字符串
- 不包含()则直接计算表达式就先判断是否包含*/
- 先计算*/再计算+-返回结果
流程图如下
四,实现过程
1,正则表达式处理用户输入的字符串
cal1.py
import re
expression = '100.5+40*5/2-3*2*2/4+9'
#\d代表数字\.代表数字意义上的小数点[\d\.]+表示可以匹配一个数字或者小数点.组成的字符串及可以代表所有数字
#匹配+及*需要加\转义
#匹配-/因为本身没有特殊函数不需要转义
l = re.findall('[\d\.]+|\+|-|\*|/',expression)
#l=['100.5', '+', '40', '*', '5', '/', '2', '-', '3', '*', '2', '*', '2', '/', '4', '+', '9']
2,首先定义出不包含()的字符串的计算方法
cal2.py
import re
expression = '100.5+40*5/2-3*2*2/4+9'
#\d代表数字\.代表数字意义上的小数点[\d\.]+表示可以匹配一个数字或者小数点.组成的字符串及可以代表所有数字
#匹配+及*需要加\转义
#匹配-/因为本身没有特殊函数不需要转义
l = re.findall('[\d\.]+|\+|-|\*|/',expression)
#l=['100.5', '+', '40', '*', '5', '/', '2', '-', '3', '*', '2', '*', '2', '/', '4', '+', '9'] #定义乘除法运算函数
def multdiv(l,x):
#l是转换后的列表,x是传递的*或者/
#首先找到第一个*或者/的位置,需要计算的即为位置前后的两个数
#本列子a = 2 l[a-1] = 40 l[a+1] = 5
a = l.index(x)
if x == '*':
k = float(l[a-1]) * float(l[a+1])
else:
k = float(l[a - 1]) / float(l[a + 1])
#依次删除找到的符号连同前后的两个元素
#本列子删除的是'40','*','5'
del l[a-1],l[a-1],l[a-1]
#把计算结果转换成字符在插入列表原位置这样就完成了一次乘法或者除法运算
#并且把结果返回生成新的列表
l.insert((a-1),str(k))
#调用多次该函数就会把*/计算出来后返回一个不包含*/的新列表
return l #定义计算函数,其中需要调用multdiv函数去除*/
def fun(l):
#函数需要传递的参数为一个列表
#定义函数需要返回的结果
sum = 0
#假如列表不为空,无限循环处理列表
while l:
#先判断列表是否包含*/执行对应的运算
#如果列表里面只有*没有/则把'*'作为实参传递给处理乘除法的函数multdiv
if '*' in l and '/' not in l:
multdiv(l,'*')
#同理处理只包含/符号的
elif '/' in l and '*' not in l:
multdiv(l,'/')
#如果列表里面既包含*又包含/则先取到对应的索引值,比较大小后先处理前面再处理后面的
elif '*' in l and '/' in l:
a = l.index('*')
b = l.index('/')
if a < b:
multdiv(l,'*')
else:
multdiv(l,'/') #到这里已经处理完*/列表只剩下数字和+-
else:
#考虑到处理完*/以后的列表第一位可能是-
#先把索引位置0 1 合并
#例如l = ['-','1'...]
#合并后l = ['-1']
if l[0] == '-':
l[0] = l[0] + l[1]
del l[1]
#处理完以后的列表只包含数字+ -
#把列表第一位赋值给sum作为起始需要计算的基数
sum += float(l[0])
#循环处理列表,因为列表的格式类似于['1','+','3','-','-4']
#所以需要取l[1] l[3] ...判断运算符号是+还是-然后根据情况进行累计加减
for i in range(1,len(l),2):
if l[i] == '+':
sum += float(l[i+1])
elif l[i] == '-':
sum -= float(l[i+1])
break
return sum print(100.5+40*5/2-3*2*2/4+9)
#206.5
a = fun(l)
print(a)
#206.5
这样处理的列表还有一个问题,假如需要处理的字符串有一串是这样的格式7*((1-4)-4) 使用fun计算一次为7*(-3-4) 再处理一次为7*(-7) 这样的字符串分割成列表为['7','*','-','7']需要在定义乘除以及加减方法的时候可以处理这种情况
cal3.py
import re
expression = '100.5+40*5/2-3*2*2/4+9'
#\d代表数字\.代表数字意义上的小数点[\d\.]+表示可以匹配一个数字或者小数点.组成的字符串及可以代表所有数字
#匹配+及*需要加\转义
#匹配-/因为本身没有特殊函数不需要转义
l = re.findall('[\d\.]+|\+|-|\*|/',expression)
#l=['100.5', '+', '40', '*', '5', '/', '2', '-', '3', '*', '2', '*', '2', '/', '4', '+', '9'] #定义乘除法运算函数
def multdiv(l,x):
#l是转换后的列表,x是传递的*或者/
#首先找到第一个*或者/的位置,需要计算的即为位置前后的两个数
#本列子a = 2 l[a-1] = 40 l[a+1] = 5
a = l.index(x)
if x == '*' and l[a+1] != '-':
k = float(l[a-1]) * float(l[a+1])
elif x == '/' and l[a+1] != '-':
k = float(l[a - 1]) / float(l[a + 1])
#如果*或者/后面对应的是-号则计算时候需要在前面加-
elif x == '*' and l[a+1] == '-':
k = -float(l[a - 1]) * float(l[a + 2])
elif x == '/' and l[a+1] == '-':
k = -float(l[a - 1]) / float(l[a + 2])
#依次删除找到的符号连同前后的两个元素
#本列子删除的是'40','*','5'
del l[a-1],l[a-1],l[a-1]
#把计算结果转换成字符在插入列表原位置这样就完成了一次乘法或者除法运算
#并且把结果返回生成新的列表
l.insert((a-1),str(k))
#调用多次该函数就会把*/计算出来后返回一个不包含*/的新列表
return l #定义计算函数,其中需要调用multdiv函数去除*/
def fun(l):
#函数需要传递的参数为一个列表
#定义函数需要返回的结果
sum = 0
#假如列表不为空,无限循环处理列表
while l:
#先判断列表是否包含*/执行对应的运算
#如果列表里面只有*没有/则把'*'作为实参传递给处理乘除法的函数multdiv
if '*' in l and '/' not in l:
multdiv(l,'*')
#同理处理只包含/符号的
elif '/' in l and '*' not in l:
multdiv(l,'/')
#如果列表里面既包含*又包含/则先取到对应的索引值,比较大小后先处理前面再处理后面的
elif '*' in l and '/' in l:
a = l.index('*')
b = l.index('/')
if a < b:
multdiv(l,'*')
else:
multdiv(l,'/') #到这里已经处理完*/列表只剩下数字和+-
else:
#考虑到处理完*/以后的列表第一位可能是-
#先把索引位置0 1 合并
#例如l = ['-','1'...]
#合并后l = ['-1']
if l[0] == '-':
l[0] = l[0] + l[1]
del l[1]
#处理完以后的列表只包含数字+ -
#把列表第一位赋值给sum作为起始需要计算的基数
sum += float(l[0])
#循环处理列表,因为列表的格式类似于['1','+','3','-','-4']
#所以需要取l[1] l[3] ...判断运算符号是+还是-然后根据情况进行累计加减
for i in range(1,len(l),2):
if l[i] == '+' and l[i+1] != '-':
sum += float(l[i+1])
elif l[i] == '-' and l[i+1] != '-':
sum -= float(l[i+1])
#如果列表中+后面对应的是-则再推后一位计算-
elif l[i] == '+' and l[i+1] == '-':
sum -= float[l[i+2]]
#如果列表中-号后面对应的是-则再推后一位--得+ 计算+
elif l[i] == '-' and l[i + 1] == '-':
sum += float[l[i+2]]
#循环完毕列表退出整个循环
break
#把计算的结果sum作为返回值返回
return sum print(100.5+40*5/2-3*2*2/4+9)
#206.5
a = fun(l)
print(a)
#206.5
以上程序可以处理不带任何括号的字符串,下面新加一个函数处理带有括号的字符串
cal4.py
import re
expression = '100.5+40*5/2-3*2*2/4+9'
#\d代表数字\.代表数字意义上的小数点[\d\.]+表示可以匹配一个数字或者小数点.组成的字符串及可以代表所有数字
#匹配+及*需要加\转义
#匹配-/因为本身没有特殊函数不需要转义
l = re.findall('[\d\.]+|\+|-|\*|/',expression)
#l=['100.5', '+', '40', '*', '5', '/', '2', '-', '3', '*', '2', '*', '2', '/', '4', '+', '9'] #定义乘除法运算函数
def multdiv(l,x):
#l是转换后的列表,x是传递的*或者/
#首先找到第一个*或者/的位置,需要计算的即为位置前后的两个数
#本列子a = 2 l[a-1] = 40 l[a+1] = 5
a = l.index(x)
if x == '*' and l[a+1] != '-':
k = float(l[a-1]) * float(l[a+1])
elif x == '/' and l[a+1] != '-':
k = float(l[a - 1]) / float(l[a + 1])
#如果*或者/后面对应的是-号则计算时候需要在前面加-
elif x == '*' and l[a+1] == '-':
k = -float(l[a - 1]) * float(l[a + 2])
elif x == '/' and l[a+1] == '-':
k = -float(l[a - 1]) / float(l[a + 2])
#依次删除找到的符号连同前后的两个元素
#本列子删除的是'40','*','5'
del l[a-1],l[a-1],l[a-1]
#把计算结果转换成字符在插入列表原位置这样就完成了一次乘法或者除法运算
#并且把结果返回生成新的列表
l.insert((a-1),str(k))
#调用多次该函数就会把*/计算出来后返回一个不包含*/的新列表
return l #定义计算函数,其中需要调用multdiv函数去除*/
def fun(s):
#函数需要传递的参数为一个字符串
#需要把字符串转换成列表
l = re.findall('[\d\.]+|\+|-|\*|/', s)
#定义函数需要返回的结果
sum = 0
#假如列表不为空,无限循环处理列表
while l:
#先判断列表是否包含*/执行对应的运算
#如果列表里面只有*没有/则把'*'作为实参传递给处理乘除法的函数multdiv
if '*' in l and '/' not in l:
multdiv(l,'*')
#同理处理只包含/符号的
elif '/' in l and '*' not in l:
multdiv(l,'/')
#如果列表里面既包含*又包含/则先取到对应的索引值,比较大小后先处理前面再处理后面的
elif '*' in l and '/' in l:
a = l.index('*')
b = l.index('/')
if a < b:
multdiv(l,'*')
else:
multdiv(l,'/') #到这里已经处理完*/列表只剩下数字和+-
else:
#考虑到处理完*/以后的列表第一位可能是-
#先把索引位置0 1 合并
#例如l = ['-','1'...]
#合并后l = ['-1']
if l[0] == '-':
l[0] = l[0] + l[1]
del l[1]
#处理完以后的列表只包含数字+ -
#把列表第一位赋值给sum作为起始需要计算的基数
sum += float(l[0])
#循环处理列表,因为列表的格式类似于['1','+','3','-','-4']
#所以需要取l[1] l[3] ...判断运算符号是+还是-然后根据情况进行累计加减
for i in range(1,len(l),2):
if l[i] == '+' and l[i+1] != '-':
sum += float(l[i+1])
elif l[i] == '-' and l[i+1] != '-':
sum -= float(l[i+1])
#如果列表中+后面对应的是-则再推后一位计算-
elif l[i] == '+' and l[i+1] == '-':
sum -= float(l[i+2])
#如果列表中-号后面对应的是-则再推后一位--得+ 计算+
elif l[i] == '-' and l[i + 1] == '-':
sum += float(l[i+2])
#循环完毕列表退出整个循环
break
#把计算的结果sum作为返回值返回
return sum #定义最终函数计算带有()的字符串
def calculate(expression):
#函数传递的是一个字符串类似于(2-1)+(4-3)*3
#定义函数的最终返回值及计算结果
ans = 0
ex = []
#如果字符串不包含(则代表处理完()直接调用函数fun返回结果即可
if '(' not in expression:
ans = fun(expression)
return ans
#否则处理()
else:
#使用search查找字符串中出现的第一个最里面的()
#\([^()]+\)的意思是查找以(开始以)结尾的并且中间不包含任何()的字符串返回一个对象
#该对象有取出的字符串以及该字符串对应的索引
ret = re.search('\([^()]+\)',expression)
temp = ret.group()
#temp = '(1+2)'
ex = ret.span()
#ex = (0,5)
#切片去除首尾的()剩下不含()的字符串
sub = temp[1:-1]
#sub = '1+2'
#把不包含()的字符串作为参数传递给fun函数计算结果
k = fun(sub)
#k = 3
#这样字符串被分为三段分别赋值给l1,l2,l3,重新拼接一下
l1 = expression[0:ex[0]]
#l1=''
l2 = str(k)
#l2='1'
l3 = expression[ex[1]:]
#l3='+(4-3)*3'
expression = l1 + l2 + l3
#第一次处理完()拼接的结果为
#expression = '3+(4-3)*3'
#递归调用函数第二次拼接后的结果是
#expression = '3+-1*3'
#以此类推直到没有()
return calculate(expression) a = calculate('1+(2-3)*5')
print(a)
Python之实现简单计算器功能的更多相关文章
- Python Django 实现简单注册功能
Python Django 实现简单注册功能 项目创建略,可参考前期文档介绍. 目录结构如下 编辑views.py from django.shortcuts import render # Crea ...
- python正则实现简单计算器
利用正则实现计算器 利用正则来实现简单计算器的功能,能够设计计算带括号的加减乘除运算.当然不使用eval等语句. 利用递归: import re from functools import reduc ...
- java实现简单计算器功能
童鞋们,是不是有使用计算器的时候,还要进入运行,输入calc,太麻烦了,有时候甚至还忘记单词怎么拼写,呵呵程序员自己写代码实现,又简单,又方便啊 以下为代码(想要生成可执行工具可参考:http://w ...
- s12-day04-work01 简单计算器功能实现
代码: #!/usr/local/env python3 ''' Author:@南非波波 Blog:http://www.cnblogs.com/songqingbo/ E-mail:qingbo. ...
- Android-Kotlin简单计算器功能
上一篇博客 Android-Kotlin-配置/入门 配置好了 AndroidStudio Kotlin 的环境: 选择包名,然后右键: 选择Class类型,会有class: 创建CounterCla ...
- [ Python - 6 ] 正则表达式实现计算器功能
要求:禁止使用eval函数.参考网上代码如下: #!_*_coding:utf-8_*_ """用户输入计算表达式,显示计算结果""" im ...
- 简单计算器 安卓 Android 作业
Android老师布置的课程作业——简单计算器 功能要求实现四则运算,参考界面见下图: 首先给各位老铁提供apk安装包以及项目压缩包,略表诚意~ github地址:https://github.com ...
- 完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能
#!/bin/usr/env python#coding=utf-8'''完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能'''try: a=int(raw_input(" ...
- python实现简单爬虫功能
在我们日常上网浏览网页的时候,经常会看到一些好看的图片,我们就希望把这些图片保存下载,或者用户用来做桌面壁纸,或者用来做设计的素材. 我们最常规的做法就是通过鼠标右键,选择另存为.但有些图片鼠标右键的 ...
随机推荐
- 【原创】打造基于Dapper的数据访问层
[原创]打造基于Dapper的数据访问层 前言 闲来无事,花几天功夫将之前项目里用到的一个数据访问层整理了出来.实现单个实体的增删改查,可执行存储过程,可输出返回参数,查询结果集可根据实际情况返回 ...
- 1-wire单总线DS18B20
要想实现单总线通信,每一个挂在总线上的从机必须拥有开路或3态输出.单总线DS18B20的DQ引脚用内部电路实现了开漏输出,其等效电路如下图: 当单片机IO引脚配置为 mcu IO引脚 电流流向 DS1 ...
- sklearn基本回归方法
https://blog.csdn.net/u010900574/article/details/52666291 博主总结和很好,方法很实用. python一些依赖库: https://www.lf ...
- IIS8.5设置 MVC HTTP 错误 404.0 - Not Found
0. 确认 设置IIS的“ISAPI和CGI限制”中的“ASP.NET v4.0.0.30319”为允许 1. 解决方案 <system.webServer> <modules ...
- MapReduce编程(七) 倒排索引构建
一.倒排索引简单介绍 倒排索引(英语:Inverted index),也常被称为反向索引.置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射. ...
- [gj]三国攻势图
三国攻势图 参考: 估计你对三国故事有点兴趣,我给你看看图说三国(大概的):
- application/x-www-form-urlencoded接口响应报文中文乱码
1.如何处理乱码 在进行接口测试时,在用httpclient post请求时,对于Content-Type:application/json来说,在写测试脚本时只需要为头信息和post请求指定相应编码 ...
- linux镜像空间
硬件采用nandflash,nandflash为8位数据宽度,没有dataflash和norflash. Nandflash空间分配为 bootstrap + u-boot + env + linux ...
- 【黑马Android】(04)数据库的创建和sql语句增删改查/LinearLayout展示列表数据/ListView的使用和BaseAdater/内容提供者创建
数据库的创建和sql语句增删改查 1. 载入驱动. 2. 连接数据库. 3. 操作数据库. 创建表: create table person( _id integer primary key, nam ...
- Tomcat7 自动加载类及检测文件变动原理
在一般的web应用开发里通常会使用开发工具(如Eclipse.IntelJ)集成tomcat,这样可以将web工程项目直接发布到tomcat中,然后一键启动.经常遇到的一种情况是直接修改一个类的源文件 ...