一,需求分析

  要求计算一串包含数字+-*/()的类似于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. 关于Xcode正确运行swift多线程

    想跳过废话直接看解决方案的可以点击这里直接跳转,我这人写博客喜欢瞎逼逼. 还有一些我看过的不错的多线程资料,在此给出链接,点击这里直接跳转查看. 近来为了做操作系统课程设计,不得不去学习了下多线程. ...

  2. C# 使用TASK处理多任务同时处理

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. centos7防火墙的关闭

    从centos7开始使用systemctl来管理服务和程序,包括了service和chkconfig. #systemctl list-unit-files|grep firewalld.servic ...

  4. php对二维数据进行排序

    PHP一维数组的排序可以用sort(),asort(),arsort()等函数,但是PHP二维数组的排序需要自定义. 方法一:(经验证,成功)   作用:对二维数组进行指定key排序 参数:$arr ...

  5. 基于Verilog语言的FIR滤波【程序和理解】

    一直想找一个简单.清晰.明了的fir滤波器的设计,终于找到了一个可以应用的,和大家分享一下,有助于FPGA新手入门. 1.说道fir滤波器,滤波系数肯定是最重要的,因为后面程序中涉及到滤波系数问题,所 ...

  6. PHP命名空间规则解析及高级功能

    日前发布的PHP .3中,最重要的一个新特性就是命名空间的加入.本文介绍了PHP命名空间的一些术语,其解析规则,以及一些高级功能的应用,希望能够帮助读者在项目中真正使用命名空间. 在这里中我们介绍了P ...

  7. tensorflow之损失函数

    #coding:utf-8 __author__ = 'similarface' import tensorflow as tf sess=tf.Session() #max(features, 0) ...

  8. 跑测试没有web环境的情况

    有时候 当你跑测试的main方法的时候,会有一些莫名其妙的错误,明明mave pom的包是全的,web跑起来不会报错,可是在main方法下就是报错了,这个时候引入  <dependency> ...

  9. 动态加载图片的Adapter

    package com.example.cc.ecustapp.Adapter; import android.app.Activity;import android.content.Context; ...

  10. linux学习笔记12--命令less

    less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...