用Python实现复杂的计算器,可以按照“()”、乘除、加减的优先级进行混合运算。主旨是对正则表达式进行学习。

设计思路:

  1.在计算式中搜索最后一个“(”,再搜索和它匹配的“)”,截取两个括号间的表达式cul。

  2.乘除的优先级高,循环搜索cul内的乘除号,进行计算后进行加减计算,得到结果ans。

  3.用ans替换“(cul)”,重新搜索括号,知道将输入的公式简化成没有括号的四则运算。

  4.对最后的四则运算计算结果。流程图如下:

设计时的注意事项:

  1.在简化计算式过程中,如3*(1-3),简化后为3*-2,在进行乘运算的时候会报错。解决措施为将乘数前的负号移至被乘数前。将算术式更换为-3*2。除法也用相同的方法处理。

  2.在出现“--”或“+-”的时候,可以把“--”替换成“+”,把“+-”替换成“-”。

代码分析:

代码的结构是这样的:


执行文件其实没啥说的!

 import os,sys
BASE_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(BASE_dir)
sys.path.append(BASE_dir)
from core import main
if __name__ == '__main__':
main.run()

calculato.py就是将文件路径添加到环境变量中

 import re
def mul(processor):      #乘运算
a = re.search(r"(\d+)?[.]?(\d+)[*]", processor).group()[:-1]
b = re.search(r"[*]\d+[.]?(\d+)?", processor).group()[1:]
ans = float(a) * float(b)
ans = str(ans)
processor_past = re.sub(r"\d+[.]?(\d+)?[*]\d+[.]?(\d+)?", ans, processor, count=1)
return processor_past
def div(processor):     #除运算
a = re.search(r"(\d+)?[.]?(\d+)[/]", processor).group()[:-1]
b = re.search(r"[/]\d+[.]?(\d+)?", processor).group()[1:]
ans = float(a) / float(b)
ans = str(ans)
processor_past = re.sub(r"\d+[.]?(\d+)?[/]\d+[.]?(\d+)?", ans, processor, count=1)
return processor_past
def add(processor):      #加运算
a=re.search("(\d+)?[.]?(\d+)[+]",processor).group()[:-1]
b=re.search("[+]\d+[.]?(\d+)?",processor).group()[1:]
ans = float(a)+float(b)
ans = str(ans)
processor_past = re.sub(r"\d+[.]?(\d+)?[+]\d+[.]?(\d+)?",ans,processor,count=1)
return processor_past
def sub(processor):      #减运算
a=re.search("\d+[.]?(\d+)?[-]",processor).group()[:-1]
b=re.search("[-]\d+[.]?(\d+)?",processor).group()[1:]
ans = float(a)-float(b)
ans = str(ans)
processor_past = re.sub(r"\d+[.]?(\d+)?[-]\d+[.]?(\d+)?",ans,processor,count=1)
return processor_past

在func.py中定义了运算的方法,由于形参是字符串形式,需将计算结果转换成字符串,然后将结果和算术式替换:如mul("3*2+1)的返回值是“6+1”。

这里还用了字符串的切片方法,删掉第一个值:[1:],删掉最后一个值为[:-1]。

以乘法为例,"*"前必须为数字,被乘数是小数的话还会有小数点和整数位,所以在正则表达式的查询关键字为r“(\d+)?[.]?(\d+)[*]”,所引出字符串后删掉最后的“*”,而“*”后紧跟的是数字,小数点和小数点后的数为非必须字符。用r"[*]\d+[.]?(\d+)?"查找。

在查询关键字时“*"和”+“为转义字符,要在字符串前加”r“

 import re
from core import func
def find_brackets(cul): #将“()”内表达式分析出来
while re.search("[(].+", cul):
cul = re.search("[(].+", cul).group()[1:]
cul = cul[::-1]
while re.search("[)].+", cul):
cul = re.search("[)].+", cul).group()[1:]
cul = cul[::-1]
return (cul) def change(search,ans,cul): #将运算结果和()里的表达式更换
search = re.sub("[+]", '\+',search)
search = re.sub("[*]", '\*',search)
cul = re.sub("[(]%s[)]"%search,ans,cul)#在正则表达式中插入变量
return cul def change_minus(search, ans, before): # 和move_minus一起移动乘除号后面的负号
search = re.sub("[+]", '\+', search)
search = re.sub("[*]", '\*', search)
after = re.sub(search, ans, before)
return after def move_minus(cul):
b = cul
if re.search(r"(\d+)?[.]?\d+[*][-](\d+)?[.]?\d+?", cul):
a = re.search(r"(\d+)?[.]?\d+[*][-](\d+)?[.]?\d+?", cul).group()
c = a
a = re.sub("[-]", "", a)
a = '-' + a
b = change_minus(c, a, cul)
elif re.search(r"(\d+)?[.]?\d+[/][-](\d+)?[.]?\d+?", cul):
a = re.search(r"(\d+)?[.]?\d+[/][-](\d+)?[.]?\d+?", cul).group()
c = a
a = re.sub("[-]", "", a)
a = '-' + a
b = change_minus(c, a, cul)
return b def mul_div(str_past): #乘除优先级一致,进行乘除运算
ans = str_past
while re.search("[\*]|[/]",ans):
res = re.search("[/]|[\*]",ans).group()
if res == "*":
ans = func.mul(ans)
elif res =="/":
ans = func.div(ans)
return ans def add_reduce(str_past): #加减优先级一致,进行加减运算
ans = str_past
ans = re.sub("--","+",ans)
ans = re.sub(r"[+][-]","-",ans)
while re.search(r"[+]|[-]",ans):
if re.match("-",ans):
break
else:
res = re.search(r"[+]|[-]",ans).group()
if res == "+":
ans = func.add(ans)
elif res =="-":
ans = func.sub(ans)
return ans def cul(str):
cul = str
ans = str
while re.search("[(]",cul):
cul = re.sub("--", "+", cul)
cul = re.sub(r"[+][-]", "-", cul)
cul_1 = find_brackets(cul)
ans = mul_div(cul_1)
ans = add_reduce(ans)
ans = change(cul_1,ans,cul)
cul = ans
cul = move_minus(cul)
ans = move_minus(ans)
ans = mul_div(ans)
ans = add_reduce(ans)
return ans

calcu.py定义了整个计算的流程。

cul()中不断索引括号,将索引出的算术式计算后用结论替代。每简化一轮后检查乘除号后是否有负号的状态。

乘除法的优先级比加减高,可以把乘除的运算放在一起,

while re.search("[\*]|[/]",ans):

用这个方法可以从左到右循环搜索算术式内的乘除运算。

 import re
import os,sys
from core import calcu,func.log
def run():
print("欢迎使用计算器!!!")
while True:
cul = input("请输入计算公式:")
if cul == "exit":
print("退出计算器!")
break
elif re.findall("[(]", cul).__len__() != re.findall("[)]", cul).__len__():
print("括号不匹配!")
elif re.search("[(]|[)]",cul):
print("请使用英文符号!")
elif re.search("[a-z]|[A-Z]",cul):
print("请输入数字!")
else:
ans = calcu.cul(cul)
print(ans)
log.logger(cul,ans)

main.py调用了整个算式的计算过程,并对输入的公式进行了一些纠错措施并在每次计算后将计算式和结论存储在日志中。

 import time
def logger(cul,ans):
fp = open("logger.txt",'a+',encoding="UTF-8")
now = time.time()
fp.write("%s %s=%s\n"%(now,cul,ans))
fp.close()

log.py就是将每次运算的公式和结论存储在日志中。

存在的问题:日志文件应存储在log路径下,但是现在每次执行完会在bin路径下生成新日志文件并进行存储操作。还在想办法改进中!

Python实现的复杂的计算器的代码的更多相关文章

  1. python 利用栈实现复杂计算器

    #第五周的作业--多功能计算器#1.实现加减乘除及括号的优先级的解析,不能使用eval功能,print(eval(equation))#2.解析复杂的计算,与真实的计算器结果一致#用户输入 1 - 2 ...

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

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

  3. python超实用的30 个简短的代码片段(三)

    Python是目前最流行的语言之一,它在数据科学.机器学习.web开发.脚本编写.自动化方面被许多人广泛使用. 它的简单和易用性造就了它如此流行的原因. 如果你正在阅读本文,那么你或多或少已经使用过P ...

  4. [转] 三种Python下载url并保存文件的代码

    原文 三种Python下载url并保存文件的代码 利用程序自己编写下载文件挺有意思的. Python中最流行的方法就是通过Http利用urllib或者urllib2模块. 当然你也可以利用ftplib ...

  5. 使用python制作ArcGIS插件(2)代码编写

    使用python制作ArcGIS插件(2)代码编写 by 李远祥 上一章节已经介绍了如何去搭建AddIn的界面,接下来要实现具体的功能,则到了具体的编程环节.由于使用的是python语言进行编程,则开 ...

  6. Python 爬虫的工具列表 附Github代码下载链接

    Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...

  7. Python中生成器和迭代器的区别(代码在Python3.5下测试):

    https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...

  8. Qt简单项目--加法计算器(详细代码注释)

    Qt的简单案例--加法计算器(详细代码注释) 一.项目结构 二.项目代码 widget.h #ifndef WIDGET_H #define WIDGET_H //预编译指令, 为了避免头文件被重复包 ...

  9. (转)Python新手写出漂亮的爬虫代码2——从json获取信息

    https://blog.csdn.net/weixin_36604953/article/details/78592943 Python新手写出漂亮的爬虫代码2——从json获取信息好久没有写关于爬 ...

随机推荐

  1. yum update 自动忽略内核更新

    系统每天凌晨 3 点自动执行 yum update 任务 但升级内核后,会出现下面情况 一些编译软件需要内核模块才能够被调用, 而内核模块需要与当前版本内核编译后才能够使用, 假设内核升级后,之前软件 ...

  2. 跨时代的分布式数据库 – 阿里云DRDS详解(转)

    原文章地址:https://www.csdn.net/article/a/2015-08-28/15827676 跨时代的分布式数据库 – 阿里云DRDS详解 发表于2015-08-28 18:39| ...

  3. PHP ActiveRecord demo栗子中 关于类名 的问题

    问题: ActiveRecord如何将单个类名与表名相关联? 我昨天才发现了ActiveRecord,很奇妙的php数据库框架. 但是,我仍然对以下工作感到困惑: 1.下面这个Person Model ...

  4. java中继承thread类的其他类的start()方法与run()方法

    java中继承thread或者实现runnable接口的类必须重写run()方法. 如果其执行了start()方法,其实就是启动了线程的run()方法. 注意:如果是实现runnable接口的类是没有 ...

  5. poj1845(逆元+快速幂)

    题目链接:https://vjudge.net/problem/POJ-1845 题意:求A的B次方的所有因子(包括1)的和对9901的模. 思路:首先对A利用唯一分解定理得A=p1x1*p2x2*. ...

  6. Centos 7 下 Corosync + Pacemaker + psc 实现 httpd 服务高可用

    一.介绍 高可用,大家可能会想到比较简单的Keepalived,或者更早一点的 heartbeat,也可能会用到 Corosync+Pacemaker,那么他们之间有什么区别. Heartbeat到了 ...

  7. Maven 添加jar包到本地仓库

    一.使用Maven命令安装jar包 前提:在windows操作系统中配置好了Maven的环境变量,怎么配置请自己百度,这里不介绍,可参考https://jingyan.baidu.com/articl ...

  8. oracle 中decode函数用法

    学习记录: 含义解释: decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译值1)ELSIF 条件=值2 ...

  9. Mobile Game Development with Unity Build Once, Deploy Anywhere

    本书从自上而下的角度介绍了Unity游戏引擎的功能,并提供了具体的.面向项目的指导,说明了如何在真实的游戏场景中使用这些功能,以及如何从头开始构建让玩家爱不释手的2D和3D游戏.主要内容有:探索Uni ...

  10. vue 打包

    1.assetsPublicPath路径改为‘./’(两处) 2.cmd运行  cnpm run build 3.生成的dist文件即可本地访问