一,需求分析

  要求计算一串包含数字+-*/()的类似于3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)表达式的数值

二,知识点

  • 正则表达式
  • 元素切片
  • 函数
  • 函数递归

三,流程分析

  1. 判断字符串是否包含()如果有先处理()内表达式并且计算结果返回新字符串
  2. 不包含()则直接计算表达式就先判断是否包含*/
  3. 先计算*/再计算+-返回结果

  流程图如下

四,实现过程

  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之实现简单计算器功能的更多相关文章

  1. Python Django 实现简单注册功能

    Python Django 实现简单注册功能 项目创建略,可参考前期文档介绍. 目录结构如下 编辑views.py from django.shortcuts import render # Crea ...

  2. python正则实现简单计算器

    利用正则实现计算器 利用正则来实现简单计算器的功能,能够设计计算带括号的加减乘除运算.当然不使用eval等语句. 利用递归: import re from functools import reduc ...

  3. java实现简单计算器功能

    童鞋们,是不是有使用计算器的时候,还要进入运行,输入calc,太麻烦了,有时候甚至还忘记单词怎么拼写,呵呵程序员自己写代码实现,又简单,又方便啊 以下为代码(想要生成可执行工具可参考:http://w ...

  4. s12-day04-work01 简单计算器功能实现

    代码: #!/usr/local/env python3 ''' Author:@南非波波 Blog:http://www.cnblogs.com/songqingbo/ E-mail:qingbo. ...

  5. Android-Kotlin简单计算器功能

    上一篇博客 Android-Kotlin-配置/入门 配置好了 AndroidStudio Kotlin 的环境: 选择包名,然后右键: 选择Class类型,会有class: 创建CounterCla ...

  6. [ Python - 6 ] 正则表达式实现计算器功能

    要求:禁止使用eval函数.参考网上代码如下: #!_*_coding:utf-8_*_ """用户输入计算表达式,显示计算结果""" im ...

  7. 简单计算器 安卓 Android 作业

    Android老师布置的课程作业——简单计算器 功能要求实现四则运算,参考界面见下图: 首先给各位老铁提供apk安装包以及项目压缩包,略表诚意~ github地址:https://github.com ...

  8. 完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能

    #!/bin/usr/env python#coding=utf-8'''完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能'''try: a=int(raw_input(" ...

  9. python实现简单爬虫功能

    在我们日常上网浏览网页的时候,经常会看到一些好看的图片,我们就希望把这些图片保存下载,或者用户用来做桌面壁纸,或者用来做设计的素材. 我们最常规的做法就是通过鼠标右键,选择另存为.但有些图片鼠标右键的 ...

随机推荐

  1. Android---Handler消息处理机制

    搞Android的人都知道.android是不同意你在子线程中更新UI操作的.这主要出于线程安全方面的考虑.通常的做法是在主线程中创建一个Handler对象,在子线程中创建一个Message对象.该M ...

  2. C语言 Linux环境变量

    /* *@author cody *@date 2014-08-12 *@description */ /* extern char **environ //environment values #i ...

  3. docker动态添加磁盘

    docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter #!/bin/bash #This script is dynamic mount ...

  4. 解决eclipse无法打开:Failed to load the JNI shared library

    64位系统安装了64位的eclipse,但是jdk是32位的 总之就是eclipse跟jdk搭配不上,所以解决的时候注意这一点

  5. Django1.6 +wsgi 部署到Apache2 的步骤。

    网上很多教程都是关于1.6之前的版本,很多都不适用,经历告诉我们最靠谱的还是官方文档. 一个Demo例子: 以 python shell开发的方式部署没有问题,但当独立部署到Apache2的过程非常艰 ...

  6. debian下为arm开发板创建基于debian或emdebian的根文件系统

    Debian系统本身包含对arm的支持,其包含的软件包最多,但是最终的文件系统要大一些. emdebian 是一个非常好用的嵌入式linux操作系统,其基于debian的特点对于熟悉debian系统的 ...

  7. 5plus

    http://124.173.121.89/wx/index.html?1410766859789

  8. VMware网络连接失败解决方法

    假如你碰到了VMware 网络被断开,明明已经分配了适配器,客户端却显示网络断开没有连接. 一. 可用恢复默认的方法重置所有网卡及服务. 如图片操作: 进主工具首页.点击: 虚拟网络编辑器 然后点击下 ...

  9. IntelliJ IDEA常用快捷键小结

    IntelliJ Idea 常用快捷键列表 Ctrl+Alt+t 选择代码块 try catch Alt+回车 导入包,自动修正Ctrl+N 查找类Ctrl+Shift+N 查找文件Ctrl+Alt+ ...

  10. shell变量自增 || Python脚本接收参数

    一.shell变量自增a=1a=$(($a+1))a=$[$a+1]a=`expr $a + 1`let a++ let a+=1 ((a++)) echo $a 二.python脚本接收参数 fro ...