嗯,稀里糊涂就居然写完了......

readme:

程序说明:
此计算器比较简单,只支持普通的加减乘除和小括号,不支持[],{},求幂之类的均不支持! 测试过的字符串:
-1/2*((60-30+(-9-2.222*-5/3*2.28/-12+7/3*99/4*2998+10*568/14)*((-40.0/5)))-(-4*3)/(16-3*2)) 思路:
1.使用正则表达式,优先匹配最内层的括号内数据
2.为了提高效率,优先把频繁用的匹配写成了compile,后期通过变量来调用
3.无法除以0,本身除以0就是个错误的逻辑....
4.按照优先级,先算括号,然后乘除,最后加减
5.运行前会测试表达式中括号是否匹配

流程图:

代码:

#!/usr/bin/env python
# -*-coding=utf-8-*-
# Auther:ccorz Mail:ccniubi@163.com Blog:http://www.cnblogs.com/ccorz/
# GitHub:https://github.com/ccorzorz import re,os #提高计算效率,使用re.compile写入正则匹配,提前编译
#匹配外部有内部没有小括号的部分
bracket_flag_str=re.compile('(\([^()]+\))')
#从左到右匹配乘除部分
mul_div_exec_str=re.compile('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*') def sign_exec(args):
"""
加减处理,将+-替换为-,--替换为+
:param args: 表达式字符串
:return: 将替换后的结果返回
"""
return re.sub(r'\+\-','-',re.sub(r'\-{2}','+',args)) def add_sub_exec(args):
"""
加减计算功能
:param args: 字符串
:return: 求和的结果
"""
if args.startswith('-'): #如果以-开头,将开头的加一个0
args='0%s'%(args)
elif args.startswith('+'): #如果以+开头,将开头的+去掉
args=re.sub(r'\+','',args)
args=re.sub(r'\-','+-',args) #将所有的-替换为+-
args_list=re.split(r'\+',args) #以+将字符串分割为列表
for i in args_list:
args_list[args_list.index(i)]=float(i) #列表中的元素转化为float类型
result=sum(args_list) #求和
return result def exec_had_drop_contect(args):
"""
处理括号内优先计算的函数
:param args: 字符串
:return: 递归函数
"""
if not mul_div_exec_str.search(args): #如果不匹配,说明已经计算完成
return args
else:
#以优先计算的部分,将字符串分割成两部分
before,after=mul_div_exec_str.split(args,1)
#优先计算部分定义变量
contect=mul_div_exec_str.search(args).group()
#如果以*分割后的列表长度大于1,计算值
if len(contect.split('*'))>1:
v1,v3=contect.split('*')
v=float(v1)*float(v3)
else:
#处理除法
v1,v3=contect.split('/')
#如果除以0,提示并退出程序
if float(v3)==float(0):
exit('\033[31;1m学渣!!!!学渣!!!!学渣!!!!能'
'特么除以0么?体育老师教的数学??!!\033[0m')
else:
#处理除法结果
v=float(v1)/float(v3)
#拼接字符串
new_str='%s%s%s'%(before,v,after)
#拼接后的字符串进行加减号处理
had_sign_exec_str=sign_exec(new_str)
#args重新赋值
args=had_sign_exec_str
return exec_had_drop_contect(args) def drop_brakets(args):
"""
括号处理函数
:param args: 字符串表达式
:return: 递归函数
"""
#如果不匹配说明已经没有括号,结束递归
if not bracket_flag_str.search(args):
return args
else:
#匹配优先的计算的内容,并且风格为3部分
before,mid,after=bracket_flag_str.split(args,1)
#打印分割部分,提示用户计算进度
print(before,mid,after)
#字符串去掉括号
had_drop_contect=mid[1:-1]
#计算优先部分,先计算乘除,再将结果进行加减运算
add_sub_result=exec_had_drop_contect(had_drop_contect)
result=add_sub_exec(add_sub_result)
#将结果返回原来的字符串,拼接为新字符串
args='%s%s%s'%(before,str(result),after)
return drop_brakets(args) def calc(args):
"""
计算数据函数,先处理括号部分,然后计算乘除,最后加减部分,返回结果
:param args: 字符串
:return: 计算结果
"""
no_brakets=drop_brakets(args)
no_mul_div=exec_had_drop_contect(no_brakets)
result=add_sub_exec(no_mul_div)
print('\033[31;1m%s\033[0m'%result) def check_formula(args):
"""
判断用户输入字符串的可用性,检查括号数量是否匹配
:param args: #字符串
:return:
"""
if len(re.findall('\(',args)) == len(re.findall('\)',args)):
return True
else:
#不匹配无法运行
print('括号数量不匹配,确认后再输入')
return False #运行主函数
if __name__ == '__main__':
#清屏
os.system('clear')
print('欢迎使用只带小括号计算器'.center(60,'*'))
inp=input('请输入你要算的表达式,除了加减乘除小括号,其他都不支持哦:')
#先将输入的字符串去掉空白部分,以免报错
inp=inp.strip()
res=check_formula(inp)
if res:
#如果字符串符合表达式格式,进行计算
calc(inp)
else:
#否则退出
exit('输入格式有误')

  

Day6作业:计算器的更多相关文章

  1. 老男孩Day6作业:计算器

    作业需求: 1.实现加减乘除及拓号优先级解析 2.用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) ...

  2. day4 作业计算器

    作业:计算器开发 (1)实现加减乘除及拓号优先级解析: (2)用户输入 1 - 2 * ( (60-30 +(-40/5) * (-9-2*5/-3 + 7 /3*99/4*2998 +10 * 56 ...

  3. python基础: day4作业计算器

    作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - ...

  4. day6作业详解

    1.day6题目 1,老男孩好声⾳选秀⼤赛评委在打分的时候呢, 可以进⾏输入. 假设, 老男孩有10个评委. 让10个评委进⾏打分, 要求, 分数必须⼤于5分, 小于10分. 电影投票. 程序先给出⼀ ...

  5. day6作业--游戏人生完善

    本节作业: 熟练使用类和模块,写一个交互性强.有冲突的程序.     一.作业目的 1.规范程序写法,要按照模块来规范书写: 2.类的使用,文件之间的调用练习: 3.思路的开阔,自己编写冲突,实现调用 ...

  6. day6作业--游戏人生

    本节作业: 熟练使用类和模块,写一个交互性强.有冲突的程序. 思路: 1.各个模块之间的调用关系,如何使用类,各种方法的使用上面: 2.学了类,以为能用来解决所有问题,东西都要写在类里面: 3.下面自 ...

  7. Day6作业及默写

    1.使⽤循环打印以下效果: 1: * ** *** **** ***** for num in range(1,6): print('*' * num) 2: ***** **** *** ** * ...

  8. day6作业(元组,字典,集合)

    默写: 1.元组 字典 集合 列表 各自的特点 2.字典添加 删除 修改 循环 必做: 1.餐厅提供了五种不同的菜,使用元组来存储他们,并循环打印出所有菜名,要求用户输入新加的菜名,加入到菜单中,并重 ...

  9. day6作业--选课系统

    角色:学校.学员.课程.讲师 要求: 1.创建北京.上海2所学校: 2.创建Linux,Python,go 3个课程,Linux\python在北京开,go在上海开: 3.课程包含,周期.价格,通过学 ...

随机推荐

  1. Nginx入门(四)——反向代理

    server { listen 8020; server_name localhost; location / { root html; index index.html index.htm; pro ...

  2. 创建型模式(一) 单例模式(Singleton)

    一.动机(Motivation) 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性.以及良好的效率. 如何绕过常规的构造器,提供一种机制来保证一个类只 ...

  3. Jenkins 参数化构建(Extended Choice Parameter)

    1.下载安装 Extended Choice Parameter 插件 2.打开job--->General--->参数化构建过程--->Extended Choice Parame ...

  4. Spring如何给静态变量注入值

    Common.java是一个工具类. Spring无法直接给静态变量注入值,因为静态变量不属于对象,只属于类,也就是说在类被加载字节码的时候变量已经初始化了,也就是给该变量分配内存了,导致spring ...

  5. GBDT算法梳理

    1.GBDT(Gradient Boosting Decision Tree)思想 Boosting : 给定初始训练数据,由此训练出第一个基学习器: 根据基学习器的表现对样本进行调整,在之前学习器做 ...

  6. React组件属性/方法/库属性

    1. propTypes 用于进行props的类型检查:来自于prop-types库. // V15.5之后 import PropTypes from 'prop-types'; 该方法适用于函数组 ...

  7. 23 | MySQL是怎么保证数据不丢的?

    今天这篇文章,我会继续和你介绍在业务高峰期临时提升性能的方法.从文章标题“MySQL是怎么保证数据不丢的?”,你就可以看出来,今天我和你介绍的方法,跟数据的可靠性有关. 在专栏前面文章和答疑篇中,我都 ...

  8. 洛谷 P2863 [USACO06JAN]牛的舞会The Cow Prom 题解

    每日一题 day11 打卡 Analysis 好久没大Tarjan了,练习练习模板. 只要在Tarjan后扫一遍si数组看是否大于1就好了. #include<iostream> #inc ...

  9. 使用webuploader实现断点续传

    核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...

  10. PHP全栈学习笔记31

    伪类:未被访问状态,已被访问状态,鼠标悬停状态,活动状态 :link 未被访问的链接添加样式 :visited 向已被访问链接添加样式 :hover 向鼠标悬停时向元素添加样式 :active 向被激 ...