已知有以下这样一个不太友好的公式:

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】使用正则表达式实现计算器练习的更多相关文章

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

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

  2. Python开发——利用正则表达式实现计算器算法

    Python开发--利用正则表达式实现计算器算法 (1)不使用eval()等系统自带的计算方法 (2)实现四则混合运算.括号优先级解析 思路: 1.字符串预处理,将所有空格去除 2.判断是否存在括号运 ...

  3. [python] 常用正则表达式爬取网页信息及分析HTML标签总结【转】

    [python] 常用正则表达式爬取网页信息及分析HTML标签总结 转http://blog.csdn.net/Eastmount/article/details/51082253 标签: pytho ...

  4. Python 进阶 - 正则表达式

    1. 正则表达式基础 1.1. 简单介绍 正则表达式并不是Python的一部分.正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十 ...

  5. python study - 正则表达式

    第 7 章 正则表达式 7.1. 概览 7.2. 个案研究:街道地址 7.3. 个案研究:罗马字母 7.3.1. 校验千位数 7.3.2. 校验百位数 7.4. 使用 {n,m} 语法 7.4.1. ...

  6. python使用正则表达式文本替换

    2D客户端编程从某种意义上来讲就是素材组织,所以,图片素材组织经常需要批量处理,python一定是最佳选择,不管是win/linux/mac都有一个简单的运行环境 举两个应用场景: 如果不是在某个文件 ...

  7. 教学项目之-通过Python实现简单的计算器

    教学项目之-通过Python实现简单的计算器   计算器开发需求 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/ ...

  8. python的正则表达式 re

    python的正则表达式 re 本模块提供了和Perl里的正则表达式类似的功能,不关是正则表达式本身还是被搜索的字符串,都可以是Unicode字符,这点不用担心,python会处理地和Ascii字符一 ...

  9. Python之正则表达式(re模块)

    本节内容 re模块介绍 使用re模块的步骤 re模块简单应用示例 关于匹配对象的说明 说说正则表达式字符串前的r前缀 re模块综合应用实例 正则表达式(Regluar Expressions)又称规则 ...

  10. Python:正则表达式详解

    正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能,正则表达式的在不同的语言中使用方式可能 ...

随机推荐

  1. Linux下面CentOS 7桌面的安装

    搭建本地yum仓库的方法 http://www.cnblogs.com/lql123/p/5952788.html 1.yum grouplist #列出yum仓库里的软件组列表 2.yum grou ...

  2. CentOS下 MySQL5.7 详细的部署安装流程

    MySQL5.7.14安装过程: 下载5.7版本:wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.14-linux-glibc2 ...

  3. BZOJ AC800纪念

    貌似没什么好纪念的...QAQQQ 好不容易水到了800还是记录一下好了....不过感觉水这么多题没有意义啊[思考熊] 然后就没有然后了恩 不过我到底是为什么才努力的呢...前途一阵迷茫,根本没有什么 ...

  4. 性能adb命令

    启动时间-冷启动启动App命令adb shell am start -W -n com.bit_health.android/.ui.common.activities.BitHealthMainAc ...

  5. CDN 实现原理

    传统未加缓存访问过程: 用户提交域名——浏览器对域名进行解释——访问目的主机IP地址——根据IP地址发送请求——得到请求数据并回复 由此我们可以得到未加CDN缓存网站的过程为 (1) 用户向浏览器提供 ...

  6. ionic实现上拉到底内容提示

    <!--html代码--> <ion-content has-bouncing = true on-drag-up="scrollDragUp()"> &l ...

  7. [CentOS] 指定命令别名:Alias & 软链接生成命令 ln -s

    参考:CentOS里alias命令详解 每天一个linux命令(35):ln 命令 1. Alias命令 功能描述:我们在进行系统的管理工作一定会有一些我们经常固定使用,但又很长的命令.那我们可以给这 ...

  8. IOS常用框架

    IOS开发中有用的第三方库 #Objective-C中最受瞩目库 [链接](https://github.com/languages​​/Objective-C/most_watched) * [th ...

  9. 大米网赚项目介绍,官方唯一客服QQ:712994168

    大米平台项目来源   QQ:712994168 大米软件本质上是一个高质量网赚项目收集和发布平台,该平台的所有项目都是经过专业的测试团队实测有效的项目和教程,只要去做绝对可以赚钱.平台里面的项目类型包 ...

  10. C# 4.0 新特性dynamic (待学习)

    随便翻看了一下dynamic,在网上拷贝了一个例子,先贴出来等有空了再慢慢消化 static void Main(string[] args) { dynamic d = new MyDynamicO ...