Python实现的复杂的计算器的代码
用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实现的复杂的计算器的代码的更多相关文章
- python 利用栈实现复杂计算器
#第五周的作业--多功能计算器#1.实现加减乘除及括号的优先级的解析,不能使用eval功能,print(eval(equation))#2.解析复杂的计算,与真实的计算器结果一致#用户输入 1 - 2 ...
- Python开发——利用正则表达式实现计算器算法
Python开发--利用正则表达式实现计算器算法 (1)不使用eval()等系统自带的计算方法 (2)实现四则混合运算.括号优先级解析 思路: 1.字符串预处理,将所有空格去除 2.判断是否存在括号运 ...
- python超实用的30 个简短的代码片段(三)
Python是目前最流行的语言之一,它在数据科学.机器学习.web开发.脚本编写.自动化方面被许多人广泛使用. 它的简单和易用性造就了它如此流行的原因. 如果你正在阅读本文,那么你或多或少已经使用过P ...
- [转] 三种Python下载url并保存文件的代码
原文 三种Python下载url并保存文件的代码 利用程序自己编写下载文件挺有意思的. Python中最流行的方法就是通过Http利用urllib或者urllib2模块. 当然你也可以利用ftplib ...
- 使用python制作ArcGIS插件(2)代码编写
使用python制作ArcGIS插件(2)代码编写 by 李远祥 上一章节已经介绍了如何去搭建AddIn的界面,接下来要实现具体的功能,则到了具体的编程环节.由于使用的是python语言进行编程,则开 ...
- Python 爬虫的工具列表 附Github代码下载链接
Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...
- Python中生成器和迭代器的区别(代码在Python3.5下测试):
https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...
- Qt简单项目--加法计算器(详细代码注释)
Qt的简单案例--加法计算器(详细代码注释) 一.项目结构 二.项目代码 widget.h #ifndef WIDGET_H #define WIDGET_H //预编译指令, 为了避免头文件被重复包 ...
- (转)Python新手写出漂亮的爬虫代码2——从json获取信息
https://blog.csdn.net/weixin_36604953/article/details/78592943 Python新手写出漂亮的爬虫代码2——从json获取信息好久没有写关于爬 ...
随机推荐
- MySQL 5.7 使用原生JSON类型
首先回顾一下JSON的语法规则: 数据在键值对中, 数据由逗号分隔, 花括号保存对象, 方括号保存数组. 按照最简单的形式,可以用下面的JSON表示: {"NAME": " ...
- c#批量更新list对象sql
注意: 1.语句中"set "后有空格, 2.最后一个if一定有值,且接连的sql字段 无 逗号 3.parameterList.Clear(); /// <summary ...
- weblogc SessionData.getNextId性能问题
参考:https://www.cnblogs.com/lemon-flm/p/7396627.html weblogic运行中持续报weblogic.servlet.internal.session. ...
- 静态方法调用内部类时候的new 问题
package tool; /** * 静态方法调用内部类时候的new 问题 */ public class aa { // 静态方法 // 静态方法new 有问题 public static voi ...
- 4. Median of Two Sorted Arrays (二分法;递归的结束条件)
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...
- Asp.net中GridView使用详解(很全,很经典 转来的)
Asp.net中GridView使用详解 效果图参考:http://hi.baidu.com/hello%5Fworld%5Fws/album/asp%2Enet中以gv开头的图片 l ...
- RocketMq --consumer自动实现负载均衡
这边使用一个producer和两个consumer是实现负载均衡. 看一下代码示例 package com.alibaba.rocketmq.example.message.model; import ...
- 在CentOS7.4上手动编译安装Mysql-5.7.20
实验环境:CentOS 7.4 mysql软件: mysql-boost-5.7.20.tar.gz 1.安装编译工具 yum -y install \ncurses \ncurses-devel \ ...
- 用户Cookie和会话Session、SessionId的关系
一.客户端用cookie保存了sessionID 客户端用cookie保存了sessionID,当我们请求服务器的时候,会把这个sessionID一起发给服务器,服务器会到内存中搜索对应的sessio ...
- css兼容性写法大全
淘宝初始化代码 body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset ...