Python开发——利用正则表达式实现计算器算法
Python开发——利用正则表达式实现计算器算法
(1)不使用eval()等系统自带的计算方法
(2)实现四则混合运算、括号优先级解析
思路:
1、字符串预处理,将所有空格去除
2、判断是否存在括号运算,若存在进行第3步,若不存在则直接进入第4步
3、利用正则表达式获取最底层括号内的四则运算表达式
4、将四则运算表达式进行预处理:表达式开头有负数时,在表达式前加上一个0
5、利用re.split()、re.findall()方法,通过加减符号,对四则运算进行拆分为乘除运算式和数字,并保留对应的位置下标。
6、利用re.split()、re.findall()方法,通过乘除符号,将乘除式拆分为乘除符号与数字,然后进行计算,并返回数值。
7、通过re.split()、re.findall()保留的下标位置,将表达式还原。
8、完成所有乘除运算之后,返回进行加减运算。
9、完成加减运算后,返回表达式进行替代。
10、通过递归函数,完成所有括号运算后。最后再完成一次四则运算即可完成所有运算。
注:在过程中,负数的处理存在三个要点:当负数出现在表达式开头、负数前面存在减法、乘除式中存在负数且不在表达式开头。
(1)当负数出现在表达式开头:在前面加上一个0
(2)负数前面存在减法:每次完成一次运算后需要进行一次符号检查替换
(3)乘除式中存在负数且不在表达式开头:将负号移到表达式最开头
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Dang import re def update_formula(calc_list,calc_operator_list):
# 通过拆分后的表达式列表与符号列表重新组合
for index,item in enumerate(calc_list):
if index == 0:
formula = item
elif index != 0:
formula += calc_operator_list[index-1] + item
return formula def negative_start_issue(formula):
#处理负数在括号内表达式开头的情形
calc_list = re.split("[+-]",formula) #通过+-符号将各个乘除运算分隔出来
calc_operator_list = re.findall("[+-]",formula) for index,item in enumerate(calc_list):
if index == 0 and item == '': # 处理负号在开头的问题
calc_list[index] = ''
else:
calc_list[index] = item.strip() formula = update_formula(calc_list,calc_operator_list)
return formula def deal_unusual_issue(formula):
# 双加减符号处理
formula = formula.replace(" ","") #去掉空格
formula = formula.replace("++","+")
formula = formula.replace("+-", "-")
formula = formula.replace("-+", "-")
formula = formula.replace("--", "+")
return formula def deal_negative_issue(formula):
# 处理乘除运算中负数的计算问题(分前后位置两种情况) # 1.负数在后
m = re.search("[0-9]+[.]*[0-9]*[*|/][-][0-9]+[.]*[0-9]*",formula)
# minus_pre = re.search("[0-9]+[.]*[0-9]*[*|/][-][0-9]+[.]*[0-9]*",formula).group()
# 注意匹配的必要项与非必要项,如:"[0-9]+[.][0-9]+[*|/][-][0-9]+[.][0-9]+"误把非必要项当做必要项。
if m:
minus_pre = m.group()
minus_pro = "-"+minus_pre.replace("-","")
formula = formula.replace(minus_pre,minus_pro)
if "*-" in formula or "/-" in formula:
return deal_negative_issue(formula) # 2.负数在前
formula = deal_unusual_issue(formula) return formula def multiply_divide(formula):
# print("[%s]"%formula,formula) # 乘除计算
calc_list = re.split("[*/]", formula)
operator_list = re.findall("[*/]", formula) # 将乘号除号通过列表方式分隔出来
# print("sub_calc_list:", sub_calc_list)
# print("sub_operator_list:", sub_operator_list) res = 0
for index2, i in enumerate(calc_list):
if index2 == 0:
res = float(i)
else:
if operator_list[index2 - 1] == '*': # 通过sub_operator_list中的index判断到底是加法还是减法,
res *= float(i)
elif operator_list[index2 - 1] == '/':
res /= float(i)
return res def add_abstract(formula):
# 加减计算 # 1.开头位置负数处理
formula = negative_start_issue(formula) # 2.双加减符号处理
formula = deal_unusual_issue(formula) # 3.加减逻辑运算
calc_list = re.split("[+-]", formula)
operator_list = re.findall("[+-]", formula) res = 0
for index, i in enumerate(calc_list):
if index == 0:
res = float(i)
else:
if operator_list[index-1] == '+':
res += float(i)
elif operator_list[index-1] == '-':
res -= float(i)
return res """
四则混合运算主函数
"""
def elementary_arithmetic(formula): # 负数处理
formula = negative_start_issue(formula)
formula = deal_negative_issue(formula) # 乘除运算
calc_list = re.split("[+-]",formula) # 通过+-符号将各个乘除运算分隔出来
calc_operator_list = re.findall("[+-]",formula)
for index1, item in enumerate(calc_list):
calc_list[index1] = str(multiply_divide(item)) #数据类型的强制转换!!!
formula = update_formula(calc_list,calc_operator_list) # 加减运算
formula = add_abstract(formula) return formula """
括号运算
""" def calculator(formula):
#数据预处理
formula = formula.replace(" ","") m = re.search("\([^()]*\)",formula)
# 判断是否需要进行括号运算
if m:
# 括号运算
# 提取最小括号运算式,计算结果,并返回。
subformula = m.group().strip("()") # 把找出来的括号剥离
print("subformula:",subformula,type(subformula))
subres = elementary_arithmetic(subformula) # 调用四则混合运算主函数
print("subres:",subres)
formula = formula.replace(m.group(), str(subres))
print("updated formula:",formula)
if "(" in formula:
return calculator(formula)
else:
print("formula result:",formula) # 除去所有括号后可能出现:1-2*-312.8
formula = elementary_arithmetic(formula) return formula
else:
return elementary_arithmetic(formula) # 以下为测试代码:
formula = "1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*9/4*28 +10 * 56/14 )) - (-4*3)/ (16-3*2) )"
print("%s = "%formula,calculator(formula))
Python开发——利用正则表达式实现计算器算法的更多相关文章
- Python实例---利用正则实现计算器[FTL版]
import re # 格式化 def format_str(str): str = str.replace('--', '+') str = str.replace('-+', '-') str = ...
- Python实例---利用正则实现计算器[参考版]
利用正则进行运算规则的计算 版本一: # import re # # ss = '1 - 2 * ((60 - 30 + (-40/5) * (9 - 2 * 5 / 3 + 7 / 3 * 99 / ...
- Python开发之【简单计算器】
开发一个简单的python计算器 1.实现加减乘除及括号优先级解析 2.用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * ...
- python中利用正则表达式匹配ip地址
现在有一道题目,要求利用python中re模块来匹配ip地址,我们应如何着手? 首先能想到的是ip地址是数字,正则表达式是如何匹配数字的呢? \d或[0-9] 对于这个问题,不要一下子上来就写匹配模式 ...
- 【Python】使用正则表达式实现计算器练习
已知有以下这样一个不太友好的公式: 1 - 2 * ( (60-30 +(-9-2-5-2*3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 ...
- Python开发【数据结构】:算法(一)
算法基础 1.什么是算法? 算法(Algorithm):一个计算过程,解决问题的方法 2.复习:递归 递归的两个特点: 调用自身 结束条件 两个重要递归函数的对比: # 由大到小 def func3( ...
- 接口自动化(Python)-利用正则表达式从返回的HTML文本中截取自己想要的值
例如一个功能接口的返回值 是一个HTML文本: 例如我们要取上图中标识的id的值,并且这个值是动态的,这是我们就需要用到正则表达式进行匹配. 如下是正则匹配的方法(代码中都有注释): 我们在真正使用的 ...
- Python开发【数据结构】:算法(二)
堆排序 1.—树与二叉树简介 树是一种数据结构 比如:目录结构 树是一种可以递归定义的数据结构 树是由n个节点组成的集合: 如果n=0,那这是一棵空树: 如果n>0,那存在1个节点作为树的根节点 ...
- 利用正则表达式模拟计算器进行字符串的计算实现eval()内置函数功能
代码感觉有点绕,刚开始学习python,相关知识点还没全部学习到,还请各位大神多多指教 import re # 定义乘法 def mul(string): mul1 = re.search('-?\d ...
随机推荐
- 改变this不要怕!!!
在之前的学习和工作中,会不必要的涉及到 改变this的指向问题: 脑子里会想到的是 apply, call, bind 这三个 可逆知道他的区别吗? 1. bind区别于 apply和call 是因为 ...
- ASP.NET MVC5 Forms登陆+权限控制(控制到Action)
一.Forms认证流程 请先参考如下网址: http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html 本文主要介绍使用自定义的身份认 ...
- SQL Server 2012 管理新特性:AlwaysOn 可用性组
SQL Server 2012 新特性(一)管理新特性:AlwaysOn 一.准备环境 1.准备4台计算机 域控制器DC1,IP地址192.168.1.1 主节点SQL1:IP地址192.168.1. ...
- ribbon 详解
ribbon 详解 1. 顶层架构 2. 简单的示例:使用ResourceTemplate方式 @Test public void testGroup(){ HttpResourceGroup htt ...
- I/O和管道
一:I/O设备 I/O(Input/Output),即输入/输出,通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出. 标准输入(STDIN):0 默认接受来自键盘的输入 标准输出(ST ...
- Linux安装git和maven的详细过程
一.使用yum安装git 当前安装环境是centos6.5 由于在CentOS6的yum源中已经有git的版本了,可以直接使用yum源进行安装 yum -y install git 由于centos6 ...
- VMwaretools、共享文件夹、全屏
VMware12.1 + Ubuntu14.04 + win10专业版 设置 共享文件夹和解决Ubuntu全屏问题. 我实在不喜欢这种敲敲打打的工作,不喜欢这种有点无聊的配置环境.我喜欢 ...
- Vue mint ui用在消息页面上拉加载下拉刷新loadmore 标记
之前总结过一个页面存在多个下拉加载的处理方式,今天再来说一下在消息页面的上拉加载和下拉刷新,基本上每个app都会有消息页面,会遇到这个需求 需求:每次加载十条数据,上拉加载下拉刷新,并且没有点击查看过 ...
- css3 box-shadow阴影(外阴影与外发光)
基础说明: 外阴影:box-shadow: X轴 Y轴 Rpx color; 属性说明(顺序依次对应): 阴影的X轴(可以使用负值) 阴影的Y轴(可以使用负值) 阴影 ...
- mysql优化2:列类型选择原则
1.字段类型优先级 整型>date,time>enum,char>varchar>blog,text 列的特点分析: 整型:定长,没有国家/地区之分,没有字符集的差异 比如ti ...