用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. sass 的安装 http://blog.csdn.net/weixin_38362146/article/details/78035971?locationNum=10&fps=1

    http://blog.csdn.net/weixin_38362146/article/details/78035971?locationNum=10&fps=1

  2. linux下安装Cmake和Sniffles

    -------------------------------------------------------------------cmake的安装------------------------- ...

  3. RepeatMasker

    1.简介 RepeatMasker是一款基于Library-based,通过相似性比对来识别重复序列,可以屏蔽序列中转座子重复序列和低复杂度序列(默认将其替换成N).提供有在线服务.RepeatMas ...

  4. 安装FP

    一.安装Oracle 11.2 64-bit数据库 1.安装数据库软件并将SEINESCM数据库还原到服务器上, 2.配置监听和TNS信息 二.安装数据库32位客户端(为SSIS配套使用).安装ORA ...

  5. OnContextMenu实现禁止鼠标右键

    OnContextMenu事件 定义和使用:oncontextmenu 事件在元素中用户右击鼠标时触发并打开上下文菜单.注意:所有浏览器都支持 oncontextmenu 事件, contextmen ...

  6. javascript学习笔记(七):事件详解

    HTML事件处理 <!DOCTYPE html> <html> <head lang="en"> <meta chaset="U ...

  7. Winform开发框架之简易工作流设计(转自 伍华聪博客)

    Winform开发框架之简易工作流设计 一讲到工作流,很多人第一反应就是这个东西很深奥,有时候又觉得离我们较为遥远,确实完善的工作流设计很多方面,而正是由于需要兼顾很多方面,一般通用的工作流都难做到尽 ...

  8. php中in_array一些问题

    var_dump(in_array(1,['s','1fsdf',12])); // true var_dump(in_array(0,[4,'erdd']));  // true 因为是要用值与数组 ...

  9. docker使用以及dockerfile编写

    一 docker常用命令 1. service docker start 2. docker images        显示所有镜像 3. docker ps [-a]          显示正在运 ...

  10. WAS 与IHS集成问题

    1.安装好WAS与IHS后 发布Web发现无法启动 查阅资料后发现缺少插件Plugins 于是去下载安装对应版本的Plugins 发现还是有问题 后来想起发布web01时,插件还未安装.因此重新发布一 ...