【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 +10 * 568/14 )) - (-4*3)/ (16-3*2) )
我们使用正则表达式的基础来练习,将此结果计算出来。
代码如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*- import re
import functools def minus_operator_handler(formula):
'''处理一些特殊的减号运算'''
minus_operators = re.split("-",formula)
calc_list = re.findall("[0-9]",formula)
if minus_operators[0] == '': # 第一个值肯定是负号
calc_list[0] = '-%s' % calc_list[0]
result = functools.reduce(lambda x,y: float(x) - float(y),calc_list)
print(" - [%s] of result is : " % formula, result )
return result def handle_minus_in_list(operator_list,calc_list):
'''
有的时候把算术符和值分开后,会出现这种情况 ['-', '-', '-'] [' ', '14969037.996825399 ', ' ', '12.0/ 10.0 ']
这需要把第2个列表中的空格都变成负号并与其后面的值拼起来
'''
for index,item in enumerate(calc_list):
if item == '':
calc_list[index+1] = item + calc_list[index+1].strip() def compute_mutiply_and_dividend(formula):
'''计算乘除的内容,这里传进来的是字符串'''
# 找出所有带*、/符号的内容
operators = re.findall("[*/]",formula)
# 以*、/为分隔符,取出所有排除掉*、/的内容
calc_list = re.split("[*/]",formula)
# 结果初始化未None
result = None
# 遍历显示数组中的索引号(index)、内容(i)
for index,i in enumerate(calc_list):
if result: # 代表不是第一次循环
if operators[index-1] == "*":
result *= float(i)
elif operators[index-1] == "/":
result /= float(i)
else:
result = float(i)
print("[%s] of result is : " %formula, result)
return result def handle_special_occactions(plus_and_minus_operators,multiply_and_dividend):
'''有时会出现这种情况 , ['-', '-'] ['1 ', ' 2 * ', '14969036.7968254'],2*...后面这段实际是 2*-14969036.7968254,需要特别处理下'''
# 遍历显示数组multiply_and_dividend中的索引号(index)、内容(i)
for index,i in enumerate(multiply_and_dividend):
# 清除空格、空白
i = i.strip()
# 如果 内容的结尾是*、/
if i.endswith("*") or i.endswith("/"):
multiply_and_dividend[index] = multiply_and_dividend[index] + plus_and_minus_operators[index] + multiply_and_dividend[index+1]
del multiply_and_dividend[index+1]
del plus_and_minus_operators[index]
return plus_and_minus_operators,multiply_and_dividend def remove_addsubtract(formula):
'''将加减组合的符号替换成合并后的符号'''
formula = formula.replace("++","+")
formula = formula.replace("--","+")
formula = formula.replace("+-","-")
formula = formula.replace("-+","-")
formula = formula.replace("- -","+")
return formula def compute(formula):
'''这里计算不带括号的内容'''
# 去掉外层的括号
formula = formula.strip("()") # strip是去除的函数
# 将加减组合的符号替换成合并后的符号
formula = remove_addsubtract(formula)
# 找出替换后剩余的所有带+、-符号的内容
plus_and_minus_operators = re.findall("[+-]",formula)
# 以+、-为分隔符,取出所有排除掉+、-的内容,即取出所有*/的内容
multiply_and_dividend = re.split("[+-]",formula)
if len(multiply_and_dividend[0].strip()) == 0: # 代表这肯定是个减号
multiply_and_dividend[1] = plus_and_minus_operators[0] + multiply_and_dividend[1]
del multiply_and_dividend[0]
del plus_and_minus_operators[0]
plus_and_minus_operators,multiply_and_dividend = handle_special_occactions(plus_and_minus_operators,multiply_and_dividend)
# 遍历显示数组multiply_and_dividend中的索引号(index)、内容(i)
for index,i in enumerate(multiply_and_dividend):
if re.search("[*/]",i):
calc_inside_result = compute_mutiply_and_dividend(i)
multiply_and_dividend[index] = calc_inside_result '''开始运算+、-'''
print(multiply_and_dividend,plus_and_minus_operators)
total_result = None # 初始化total_result
# 遍历显示数组multiply_and_dividend中的索引号(index)、内容(item)
for index,item in enumerate(multiply_and_dividend):
if total_result: # 代表不是第一次循环
if plus_and_minus_operators[index-1] == "+":
total_result += float(item)
elif plus_and_minus_operators[index-1] == "-":
total_result -= float(item)
else:
total_result = float(item)
print("[%s] of result is : " %formula,total_result)
return total_result def calc(formula):
'''计算程序主入口, 主要逻辑是先计算括号里的值,算出来后再算乘除,再算加减'''
#给括号的状态设置初始值,假定括号存在
parenthesis_flag = True
#初始化运算结果为None,还没开始运算
calc_result = None
while parenthesis_flag:
#找到最里面一层的括号。正则表达式:()中间没有()的所有字符
inside = re.search("\([^()]*\)",formula)
if inside:
# 先计算括号里面的值
calc_inside_result = compute(inside.group())
formula = formula.replace(inside.group(),str(calc_inside_result))
else:
print('\033[41;1m~~~没括号了~~~\033[0m')
print('The End Result is : ',compute(formula))
# 公式中的括号都被剔除了
parenthesis_flag = False #程序的入口
if __name__ == '__main__':
result = calc("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 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")
【Python】使用正则表达式实现计算器练习的更多相关文章
- [ Python - 6 ] 正则表达式实现计算器功能
要求:禁止使用eval函数.参考网上代码如下: #!_*_coding:utf-8_*_ """用户输入计算表达式,显示计算结果""" im ...
- Python开发——利用正则表达式实现计算器算法
Python开发--利用正则表达式实现计算器算法 (1)不使用eval()等系统自带的计算方法 (2)实现四则混合运算.括号优先级解析 思路: 1.字符串预处理,将所有空格去除 2.判断是否存在括号运 ...
- [python] 常用正则表达式爬取网页信息及分析HTML标签总结【转】
[python] 常用正则表达式爬取网页信息及分析HTML标签总结 转http://blog.csdn.net/Eastmount/article/details/51082253 标签: pytho ...
- Python 进阶 - 正则表达式
1. 正则表达式基础 1.1. 简单介绍 正则表达式并不是Python的一部分.正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十 ...
- python study - 正则表达式
第 7 章 正则表达式 7.1. 概览 7.2. 个案研究:街道地址 7.3. 个案研究:罗马字母 7.3.1. 校验千位数 7.3.2. 校验百位数 7.4. 使用 {n,m} 语法 7.4.1. ...
- python使用正则表达式文本替换
2D客户端编程从某种意义上来讲就是素材组织,所以,图片素材组织经常需要批量处理,python一定是最佳选择,不管是win/linux/mac都有一个简单的运行环境 举两个应用场景: 如果不是在某个文件 ...
- 教学项目之-通过Python实现简单的计算器
教学项目之-通过Python实现简单的计算器 计算器开发需求 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/ ...
- python的正则表达式 re
python的正则表达式 re 本模块提供了和Perl里的正则表达式类似的功能,不关是正则表达式本身还是被搜索的字符串,都可以是Unicode字符,这点不用担心,python会处理地和Ascii字符一 ...
- Python之正则表达式(re模块)
本节内容 re模块介绍 使用re模块的步骤 re模块简单应用示例 关于匹配对象的说明 说说正则表达式字符串前的r前缀 re模块综合应用实例 正则表达式(Regluar Expressions)又称规则 ...
- Python:正则表达式详解
正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能,正则表达式的在不同的语言中使用方式可能 ...
随机推荐
- win32 Dll 中添加afx.h 出现如下错误 error LNK2005: _DllMain@12 already defined
win32 Dll 中添加afx.h 出现如下错误 nafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in ...
- gulp教程之gulp-minify-css
简介: 使用gulp-minify-css压缩css文件,减小文件大小,并给引用url添加版本号避免缓存.重要:gulp-minify-css已经被废弃,请使用gulp-clean-css,用法一致. ...
- xtrapivotcontrol 控件用法及相关属性
XtraPivotControl使用指南:可参照以下的文档: 转载自:http://wenku.baidu.com/view/d7886b20aaea998fcc220e53.html 上面链接中对x ...
- .NET的面向对象
一.继承 1.C#中的继承规则 继承是可传递的 派生类是对基类的扩展 构造函数和析构函数不能被继承 派生类可以覆盖已继承的成员 派生类只能从一个类中继承,可以通过接口来实现多重继承 类可以定义虚属性. ...
- vue新建项目
一直都被如何用vue.js新建一个项目的问题困扰着,经过好久的实践,终于搞清楚如何用vue新建项目了: 1.官网对于vue-cli介绍: Vue.js provides an official CLI ...
- js面向对象的使用方法
标准用法: function Sprite(){ //函数内容部设置属性 this.name='shimily'; } //原型上设置方法 Sprite.prototype.show=function ...
- Reveal for mac延长30天试用的简单方法
在iOS逆向过程中经常使用Reveal来远程查看iOS平台应用的UI布局,但Reveal有30天使用限制,经常隔一段时间想使用的时候发现已经过期了,如图: 此时在OS X中打开命令行终端,输入以下命令 ...
- 从.NET平台调用Win32 API
MSDN文章<Microsoft Win32 to Microsoft .NET Framework API Map> 介绍了.net 类库对win32的封装 从.NET平台调用Win32 ...
- 实现UniqueAttribute唯一性约束,sqlunique约束[转]
using System; using System.ComponentModel.DataAnnotations; using System.Data.Entity; namespace Zwj.T ...
- 1千万英国用户被Cryptolocker勒索软件瞄准
英国国家打击犯罪调查局(NCA)发布国家紧急警报,警报一场大规模的垃圾邮件,这些邮件中包含了一款名为CryptoLocker的勒索程序,把目标瞄准了1千万英国的email用户,该程序会加密用户的文档, ...