头疼,其实这个程序在我看的视频当中是当做re模块的运用来进行测试的,而到了我这里就成了简化版的了,因为我实在是做吐了,恕小弟无能,只能做简化版的。为何说是简化版呢,因为要求是给的计算式是多层嵌套的小括号“()”,然后计算的时候不能用eval方法,eval是个好东西啊,他能直接得到字符串中的结果,比如eval(“23+34*45/345-34”)=结果,是可以直接给你返回算术式的结果的,如果你自己处理这段字符串的话就要花好多工夫拆解字符串。我的简化版是将多层小括号给分为了小括号“()”、中括号“【】”、大括号“{}”,不允许使用多层相同括号连续嵌套(相应的不允许超过三层,超过三层,小弟无能为力),而我觉得,想要区分不同的层级的小括号“(()())”是需要下功夫用re正则去匹配的,而我这个用是用到正则了,但用的很少,重点全在如何自己写代码实现eval的功能了。

效果图:

另附一张各步骤计算详解

源代码:

import re

def Get_FuH(As):
As = As.replace('--','+')
As = As.replace('+-', '+')
As = As.replace('/-', '/')
As = As.replace('*-', '*')
End = []
As = list(As)
if (As[1] == '-'):
As.pop(1)
for i in As:
if(i == '/' or i == '+' or i == '*' ):
End.append(i)
elif(i == '-'):
End.append('+')
for i in End:
if(i == ''):
End.pop(End.index('')) return End
def Get_Num(As):
As = As.replace('--', '-')
As = As.replace('+-', '-')
As = As.replace('/-', '-')
As = As.replace('*-', '-')
As = list(As)
Get = []
End = []
for i in As:
if(i <= "9" and i >= "0" or i == '.'):
Get.append(i)
else:
End.append(''.join(Get))
Get = []
if(i == '-'):Get.append(i)
for i in End:
if(i == ''):
End.pop(End.index(''))
for i in End:
if(i == ''):
End.pop(End.index(i))
return End def Do_Xiao(As):
a = re.findall("\([+\-*/0-9.]*\)",As)
# print(a)
for i in a:
TiH = i
ShuZ = Get_Num(TiH)
FuH = Get_FuH(TiH)
ShuZ_New = []
FuH_New = []
# print(TiH)
# print(ShuZ)
# print(FuH)
for q in FuH:
if (q == '*'):
m = FuH.index('*')
End = float(ShuZ[m]) * float(ShuZ[m + 1])
ShuZ[m] = 0
FuH[m] = 0
ShuZ[m+1] = End
elif (q == '/'):
m = FuH.index('/')
End = float(ShuZ[m]) / float(ShuZ[m + 1])
ShuZ[m] = 0
FuH[m] = 0
ShuZ[m + 1] = End
for i in ShuZ:
if (i != 0): ShuZ_New.append(i)
for i in FuH:
if (i != 0): FuH_New.append(i)
# print(ShuZ_New)
# print(FuH_New)
for i in FuH_New:
if (i == '+'):
n = FuH_New.index('+')
End = float(ShuZ_New[n]) + float(ShuZ_New[n + 1])
ShuZ_New[n] = 0
FuH_New[n] = 0
ShuZ_New[n + 1] = float(End)
elif (i == '-'):
n = FuH_New.index('-')
End = float(ShuZ_New[n]) - float(ShuZ_New[n + 1])
ShuZ_New[n] = 0
FuH_New[n] = 0
ShuZ_New[n + 1] = float(End)
for p in ShuZ_New:
if (p != 0):
As = As.replace(TiH, str(p))
return As
def Do_Zhong(As):
As = As.replace("[","(")
As = As.replace("]",")")
As = Do_Xiao(As)
return As def Do_Da(As):
As = As.replace("{","(")
As = As.replace("}",")")
# print(As)
As = Do_Xiao(As)
return As def End_end(As):
As = '(' + As + ')'
End = Do_Xiao(As)
return End if __name__ == '__main__':
AA = "1-2*{[60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14)]-(-4*3)/(16-3*2)}"
BB = "34+45*{44+34*45+44/45}-{[34*45/44]*(456+466*345-3445/455)}"
As = input("请输入你要计算的式子:")
As = Do_Xiao(As)
print(As)
As = Do_Zhong(As)
print(As)
As = Do_Da(As)
print(As)
End = End_end(As)
print(End) 解析:我的整体思路很简单,就是按顺序一步步提取,先用正则把小括号的内容提取出来,因为有格式要求,所以提取的小括号的内容都是闭合的(即()中间不会出现()或者单边括号,匹配较为容易)。对提取的内容进行处理:定义了几个函数:1、提取数字,我将提取的字符串转为列表,然后把通过运算符分割的数字(之所以取运算符是因为有多位数还有小数点的存在,这样可以将一个数字完整的存放在一起)按个存放到一个列表中。2、提取运算符,直接扫描字符串列表提取即可。3、运算,因为运算符是两个数进行运算,所以通过循环运算符,每一个运算符都是运算符左右两个数的和。为了区分优先级(先乘除后加减),我进行了两边循环符号,且第二遍循环是在第一次的基础上删除了乘除运算符后的列表。即第一遍循环只算乘除,第二遍再算加减。4、中括号转小括号,一定要在小括号运算完,公式中没有小括号才能调用。5、大括号转小括号,同理中括号,因为如果大括号转成小括号,里面还有中括号会卡在中括号上没有匹配符。
再说说中间的遇到的一些bug,也是导致代码混乱的地方,这些我都没来的及优化,测视了两个算术式没问题就不搞了,头疼。1、提取数字,“-”是个大问题,到底把他算在运算符列表中呢还是算在数字列表中呢,我选择的是放在数字中,即数字分正负,由此我需要判断“+-”、“--”、“/-”、“*-”,后两个还好说,前两个真是搞死了,就在那算负负、正正的逻辑去了,还要在表达式中进行替换工作,将双符号进行缩减成标准的单符号传进符号列表中,因为符号列表的数目一旦不对,就会导致数字列表没有匹配正确(这也是最麻烦的地方,中间出了好几次超出列表范围的bug)。另一个问题比较严重的问题是在乘除算完给加减新的列表的时候,因为有连乘连除的存在,所以我需要将计算的结果再存到列比中循环利用,我的方法是算一个弹出一个,既可以继续运行,还可以缩减列表,到最后符号列表为空,数字列表还剩一个结果。呵呵,理想很丰满,结果最大的bug出来了,找了好半天,把所有的循环都输出了一遍才找到原因:因为我是用for循环,通过i in 符号列表,然后当i匹配到运算符,就找到这个下表,然后弹出去这个运算符元素,数字列表弹出去两个数字,但当我符号弹出去这个后,列表索引自动迁移,导致i+1成了i,i+1还没进行循环,就变成了下一次循环到了i+2,简单说就是每一次循环i+1,当我弹出当前位置i后,i(y) = i+1,且这是在本次循环结束前,所以当下一次循环开始时,其实是y+1,也就是上一次循环中的i(i已经被弹出去了,i成了i+1)的后面的后面这个元素,及跳过了一个i的循环,为了避免这种情况,我不弹出元素,而是全都初始化为0,当乘除运算完后,再进行“除0”,即构造新列表再次进行加减运算。
使用说明:大、中、小括号必须数目,位置等对称,且不能乱套,中规中举的小中大或者小中、小大、中大,不可小套大。式子中用到那种括号就调用一次对应的函数,且从小往大一层层的调。我没有设检查式子是否合规,讲道理应该不会再出什么问题了,AA的式子是我照着这个写的程序,BB是用来测试的,我只测试了这一个,毕竟长公式写起来也麻烦,自己再在手机上算一遍也麻烦,但AA、BB的式子我都在手机上算过了,都对,且更精确。

Python学习之函数(多层函数)、re模块的正则匹配--计算复杂加减乘除的更多相关文章

  1. Python学习笔记之常用函数及说明

    Python学习笔记之常用函数及说明 俗话说"好记性不如烂笔头",老祖宗们几千年总结出来的东西还是有些道理的,所以,常用的东西也要记下来,不记不知道,一记吓一跳,乖乖,函数咋这么多 ...

  2. 常用的re模块的正则匹配的表达式

    07.01自我总结 常用的re模块的正则匹配的表达式 一.校验数字的表达式 1.数字 ^[0-9]\*$ 2.n位的数字 ^\d{n}$ 3.至少n位的数字 ^\d{n,}$ 4.m-n位的数字 ^\ ...

  3. Python学习笔记4(函数与模块)

    1.Python程序的结构 Python的程序由包(package).模块(module)和函数组成. 模块是处理一类问题的集合,由函数和类组成. 包是由一系列模块组成的集合.包是一个完成特定任务的工 ...

  4. python 学习笔记6(函数)

    函数 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 1.减少代码重复 2.保持代码的一致性 3.方便修改,可扩展性 函数的创建 #简单 ...

  5. python学习交流 - 内置函数使用方法和应用举例

    内置函数 python提供了68个内置函数,在使用过程中用户不再需要定义函数来实现内置函数支持的功能.更重要的是内置函数的算法是经过python作者优化的,并且部分是使用c语言实现,通常来说使用内置函 ...

  6. Python学习笔记 - 高阶函数

    高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...

  7. Python学习(六) —— 函数

    一.函数的定义和调用 为什么要用函数:例如,计算一个数据的长度,可以用一段代码实现,每次需要计算数据的长度都可以用这段代码,如果是一段代码,可读性差,重复代码多: 但是如果把这段代码封装成一个函数,用 ...

  8. Python学习笔记010——匿名函数lambda

    1 语法 my_lambda = lambda arg1, arg2 : arg1 + arg2 + 1 arg1.arg2:参数 arg1 + arg2 + 1 :表达式 2 描述 匿名函数不需要r ...

  9. [python学习] 语言基础—排序函数(sort()、sorted()、argsort()函数)

    python的内建排序函数有 sort.sorted两个. 1.基础的序列升序排序直接调用sorted()方法即可 ls = list([5, 2, 3, 1, 4]) new_ls = sorted ...

随机推荐

  1. DELPHI指针的使用

    DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才 ...

  2. csdn自动生成目录索引、插入代码片快捷键

    文章目录 自动生成目录索引 插入代码片 自动生成目录索引 文章开头加入 @[TOC](目录描述) 目录描述可不写 插入代码片 cmd/ctrl + shift + k

  3. 河南理工大学算法协会暑期集训积分赛(二)网络同步赛-Numbers of interval-尺取法

    原题链接:https://hpuoj.com/contest/24/problem/E/ 思路:一般的尺取法,不断更新左端点的值. #include<iostream> #include& ...

  4. 通过java进行电脑屏幕截图

    package image; import java.awt.Desktop; import java.awt.Dimension; import java.awt.Rectangle; import ...

  5. Java 11 发布计划来了,已确定 3个 新特性!!

    Oracle 已经发布了 Java Development Kit 10,下一个版本 JDK 11 也在准备之中了.按照 Java 新的版本发布标准,Java 11 将在 6 个月后到来,现在它还只有 ...

  6. 基于Java Properties类设置本地配置文件

    一.Java Properties类介绍 Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件, ...

  7. vc 识别移动硬盘 U盘,本地硬盘

    说明:有时候我们在做设备监控的时候,要识别一些链接设备,在使用函数GetDriveType的时候,U盘可以返回DRIVE_REMOVABLE,而本地硬盘硬盘和移动硬盘DRIVE_FIXED,因此还需要 ...

  8. opensuse 通过composer安装drush工具

    由于笔者的opensuse已安装好composer,所以按照官方网站的文章 Installing/Upgrading Drush on Ubuntu,使用composer形式安装drush工具. co ...

  9. php7 mysql_pconnect() 缺失 解决方法

    php7 兼容 MySQL 相关函数 PHP7 废除了 ”mysql.dll” ,推荐使用 mysqli 或者 pdo_mysql http://PHP.net/manual/zh/mysqlinfo ...

  10. ActiveMQ 传输协议

    配置 ActiveMQ安装目录的conf/activemq.xml中的<transportConnectors>标签之内. 配置示例 TCP(默认协议,性能相对可靠) Transmissi ...