day4 作业计算器
作业:计算器开发
(1)实现加减乘除及拓号优先级解析;
(2)用户输入 1 - 2 * ( (60-30 +(-40/5) * (-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实的计算器所得出的结果一致。
思路:
(1)首先我们要找到内存括号中的内容,使用正则表达式,在这里,内存括号中我们选取比较复杂的(-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 );
(2)找到内存括号中的内容之后,我们只要对内层括号中的内容就行计算,接下来只要重复找内存括号即可;
(3)首先把找到的内存字符串括号去掉-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14;
(4)然后我们在进行修正,把字符串中的空格去掉,把“+-”转化为“-”,把“--”转化为“=”号;
(5)-9-2*5/-3+7/3*99/4*2998+10*568/14,这是上面整理得到的,下面,我们对它进行分割处理,以“+-”进行分割,并且提取字符串中所有的“+-”,放在两个列表中sign=["-","-","-","+","+"],formula_list = ["","9","2*5/","3","7/3*99/4*2998","10*568/14"];
(6)上面我们虽然得到了两个列表,但是我们发现,formula_list中包含"",这个会影响我们后续的运算,列表中还包含"2*5/",说明这个地方的列表后面跟着一个负数,我们必须进行处理,把这个接上,这样才能够正确的运算;
(7)处理"",得到sign=["-","-","+","+"],formula_list = ["-9","2*5/","3","7/3*99/4*2998","10*568/14"]
(8)处理"2*5/",这里要拼接后面的负数,得到sign=["-",,"+","+"],formula_list = ["-9","2*5/-3","7/3*99/4*2998","10*568/14"]
(9)下面,我们来执行乘除运算,把列表formula_list传递给处理乘除的函数,让里面的乘除进行运算,得到如下格式;
(10)formula_list = ["-9",-3.33334,173134.00001,405.71],然后把这个列表返回回去,执行加减运算;
(11)处理加减的函数接到参数,并且执行加减运算,得到结果res;
(12)用res替换正则匹配出来的字符串,如上面程序一直循环,即可得到结果;
插入一个别人写的代码,这是我见过写的最好的代码,思路环环相扣,很考验一个人的逻辑能力,思维能力,我看了几遍弄到了原理,并且坚持自己谢了一遍。如下:
import re def operator_update(formula):
# 对formula公式进行 去除空字符,更新运算符处理
formula = formula.replace(" ", "") # 去除空字符
formula = formula.replace("+-", "-")
formula = formula.replace("--", "+")
return formula def calc_muldiv(formula_list):
'''
计算公式里面的乘除
:param formula: 列表
:return:
'''
for index, element in enumerate(formula_list):
if "*" in element or "/" in element:
operators = re.findall("[*/]", element)
calc_list = re.split("[*/]", element)
num = None
for i, e in enumerate(calc_list):
if num:
if operators[i - ] == "*":
num *= float(e)
elif operators[i - ] == "/":
num /= float(e)
else:
num = float(e)
formula_list[index] = num
return formula_list def calc_plumin(operators, num_list):
'''
计算列表数字的加减
:param operators: 运算符列表
:param num_list: 进行运算的数字列表
:return: 返回计算结果
'''
num = None
for i, e in enumerate(num_list):
if num:
if operators[i - ] == "+":
num += float(e)
elif operators[i - ] == "-":
num -= float(e)
else:
num = float(e)
return num def merge(plus_minus_operator, multiply_divide_list):
'''
把列表中这样的形式'2*' '-3*' '5/3*' '4/2'合并到一块
:param formula_list:
:return:
'''
for index, element in enumerate(multiply_divide_list):
if element.endswith("*") or element.endswith("/"):
multiply_divide_list[index] = element + plus_minus_operator[index] + multiply_divide_list[index + ]
del multiply_divide_list[index + ]
del plus_minus_operator[index]
return merge(plus_minus_operator, multiply_divide_list)
return plus_minus_operator, multiply_divide_list def bracket_calc(formula):
'''
对括号最内层的formula公式进行计算
:param formula:
:return:
'''
formula = re.sub("[()]", "", formula) # 去除两边的()
formula = operator_update(formula)
plus_minus_operator = re.findall("[+-]", formula) # 列表 '+' '-' 运算符
multiply_divide_list = re.split("[+-]", formula) # 列表 有'*' '/'
if multiply_divide_list[] == "": # multiply_divide_list列表第一个字符为空的话,表示一个数字为负号
multiply_divide_list[] = "-" + multiply_divide_list[]
del plus_minus_operator[]
del multiply_divide_list[]
res = merge(plus_minus_operator, multiply_divide_list)
plus_minus_operator = res[] # 列表 '+' '-' 运算符 进行合并处理
multiply_divide_list = res[]
plus_minus_list = calc_muldiv(multiply_divide_list) # 生成只进行加减运算的列表
res = calc_plumin(plus_minus_operator, plus_minus_list)
return res def calculate(formula):
'''计算程序主入口, 主要逻辑是先计算拓号里的值,算出来后再算乘除,再算加减'''
while True:
formula_depth = re.search("\([^()]+\)", formula)
if formula_depth:
formula_depth = formula_depth.group()
res = bracket_calc(formula_depth)
formula = formula.replace(formula_depth, str(res))
print("\33[34;1m%s\33[0m" % (formula))
else:
res = bracket_calc(formula)
print("\33[31;1m结果:%s\33[0m" % (res))
exit() if __name__ == '__main__':
formula = "1 - 2 * ( (60-30 +(-9-2- 5-2*-3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) -(-4*3)/ (16-3*2) )"
calculate(formula)
我在上面的思路上自己谢了一遍,没有看代码,自己按照思路谢了一遍,这个还要继续研究,里面用到了很多方法。字符串的分裂,findall()等很多方法,还有当元素不存在的时候,如果先创建,还有-=,+=,*=,/=等方法,元素里面的值遍历之后相乘相除的情况:
import re
#导入正则模块
formula = "1 - 2 * ( (60-30 +(-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 ) * (-40/5)) - (-4*3)/ (16-3*2) )" def formula_update(formula_deep):
#对字符串formula_deep进行修整,去除空格,转换+-为-,转换--为+操作
formula_deep = formula_deep.replace(" ","") #去除空格
formula_deep = formula_deep.replace("+-","-")
formula_deep = formula_deep.replace("--","+")
return formula_deep def formula_correct(operator_signs,formula_list):
if formula_list[] == "":
# 如果列表中第一个元素是"",说明元素前面是一个"-"号,此时,是没有必要分割的,因为是-,分割会出现错误,所以先进行判断
formula_list[] = "-" + formula_list[]
del operator_signs[]
del formula_list[]
print(operator_signs)
print(formula_list)
for i,e in enumerate(formula_list):
if e.endswith("*") or e.endswith("/"):
formula_list[i] = e + "-" + formula_list[i+]
del operator_signs[i]
del formula_list[i+]
return operator_signs,formula_list def muldiv(formula_list):
for index,element in enumerate(formula_list):
if "*" in element or "/" in element:
muldiv_signs = re.findall("[/*]",element)
muldiv_lists = re.split("[/*]",element)
num = None
for i,e in enumerate(muldiv_lists):
if num:
if muldiv_signs[i-] == "*":
num *= float(e)
elif muldiv_signs[i-] == "/":
num /= float(e)
else:
num = float(e)
formula_list[index] = num
return formula_list def add_min(operator_signs,formula_list):
num = None
for i,e in enumerate(formula_list):
if num:
if operator_signs[i-] == "+":
num += float(e)
elif operator_signs[i-] == "-":
num -= float(e)
else:
num = float(e)
return num def handle(formula_deep):
formula_deep = re.sub("[()]", "", formula_deep)
# 去除字符串的括号,然后进一步执行,去除空格,以及转换+-以及--
formula_deep = formula_update(formula_deep)
# 对字符串进行修整,去除空格处理等
operator_signs = re.findall("[+-]", formula_deep)
# 生成字符串中运算符的列表,因为要先执行乘法,要保留之前的运算符号,以便执行乘法后能够执行加减
formula_list = re.split("[+-]", formula_deep)
# 生成列表,列表的作用是执行运算的元素,列表中有一些不合理的地方需要修正
ret = formula_correct(operator_signs, formula_list)
# 对列表进行修正,修正列表开头元素是"",元素结尾是"/",或"*"的情况
operator_signs = ret[]
# 得到新的运算符号
formula_list = ret[]
# 得到新的运算列表
# 执行乘法运算
formula_list = muldiv(formula_list)
# 得到不包含乘除的列表,下面只需要执行加减即可
res = add_min(operator_signs, formula_list)
return res def main(formula):
while True:
formula_deep = re.search("\([^()]+\)",formula)
#匹配内层括号,处理内存括号中的内容,来回循环,即可满足条件
if formula_deep:
#匹配的内容不为空的时候执行程序,当匹配不到括号的时候,说明已经匹配结束了,里面不包含括号了
formula_deep = formula_deep.group()
res = handle(formula_deep)
formula = formula.replace(formula_deep,str(res))
else:
res = handle(formula)
print(res)
exit()
if __name__ == "__main__":
formula = "1 - 2 * ( (60-30 +(-40/5) * (-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )"
main(formula)
运行结果如下:
[]
['-40/5']
['-', '-', '+', '+']
['-9', '2*5/', '3', '7/3*99/4*2998', '10*568/14']
['-', '-']
['60', '30', '8.0*173534.54761904766']
[]
['-4*3']
['-']
['16', '3*2']
['+']
['-1388246.3809523813', '12.0/10.0']
['-', '-']
['1', '2*', '1388245.1809523813']
result: 2776491.3619047627
day4 作业计算器的更多相关文章
- python基础: day4作业计算器
作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - ...
- day4作业
作业内容:计算器 #!/usr/bin/env python # -*- coding:utf-8 -*- import re,time #加减字符处理函数 def handle_symbol(cal ...
- day4作业模拟实现一个ATM + 购物商城程序
作业需求: 模拟实现一个ATM + 购物商城程序 1.额度 15000或自定义: 2.实现购物商城,买东西加入 购物车,调用信用卡接口结账: 3.可以提现,手续费5%: 4.每月22号出账单,每月10 ...
- 老男孩Day4作业:员工信息查询系统
1.作业需求: (1).工信息表程序,实现增删改查操作: (2).可进行模糊查询,语法至少支持下面3种: select name,age from staff_table where ...
- Day4作业:蛋疼CRM系统
先上流程图,还得27寸4K显示器,画图各种爽: ReadMe: 运行程序前的提示: 1.抱歉,你得装prettytable模块...... 2.还得抱歉,如果shell中运行,最好把字体调得小点,表格 ...
- Day6作业:计算器
嗯,稀里糊涂就居然写完了...... readme: 程序说明: 此计算器比较简单,只支持普通的加减乘除和小括号,不支持[],{},求幂之类的均不支持! 测试过的字符串: -1/2*((60-30+( ...
- Python3.5 day4作业:对员工信息文件,实现增删改查操作。
需求: 1.可进行模糊查询,语法至少支持下面3种: 1.select name,age from staff_table where age > 22 2.select * from staf ...
- day4作业之信息表
实在是太low了,终究是自己写的,记录下 #!/usr/bin/env python # coding=utf8 import os, re #这里我把查询这块分为3个函数了,纠结了很久是放一起还是分 ...
- day4作业小代码练习
登录模块: 我们无论上那个网站,经常遇到这样的情况,让我们登录这个网站,流程图如下: 思路: 1.当我们登录网站的时候,我们首先会输入用户名,这个时候,有些网站会提醒我们用户名是否存在,如果我们输入的 ...
随机推荐
- [转]从头开始 GAN
1 前言 GAN的火爆想必大家都很清楚了,各种GAN像雨后春笋一样冒出来,大家也都可以名正言顺的说脏话了[微笑脸].虽然目前GAN的酷炫应用还集中在图像生成上,但是GAN也已经拓展到NLP,Robot ...
- jetbrains phpstorm插件开发环境搭建
2018.04.14 重要更新: 使用 gradle 进行构建可以免去下面大部分步骤,使用 gradle 我们仅需下载安装 JDK.Idea. 使用 gradle 的方法是,新建 Project,然后 ...
- CSUST 四月选拔赛个人题解
这场比赛演的逼真,感谢队友不杀之恩 总结:卡题了赶紧换,手上捏着的题尽快上机解决 http://csustacm.com:4803/ 1113~1122 1113:六学家 题意:找出满足ai+aj=a ...
- bzoj 1003 最短路+dp
1003: [ZJOI2006]物流运输 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8249 Solved: 3464[Submit][Stat ...
- WPF系列之一:基于并行任务和MVVM创建响应灵敏和数据驱动的UI
在利用WPF创建桌面应用程序的界面时,经常使用MVVM的设计模式,以减少UI层与逻辑层的代码耦合度. 在MVVM的设计中,最主要的方法和技术是UI中的控件利用Binding来和逻辑层(ViewMode ...
- NAIPC2018-K-Zoning Houses
题目描述 Given a registry of all houses in your state or province, you would like to know the minimum si ...
- How to Evaluate Machine Learning Models, Part 4: Hyperparameter Tuning
How to Evaluate Machine Learning Models, Part 4: Hyperparameter Tuning In the realm of machine learn ...
- JVM学习十二:JVM之性能监控工具
前面我们学习了很多JVM相关的理论知识,那么本节将重点讲述的是工具的使用,正所谓:工欲善其事,必先利其器.因此,本节介绍常用的性能监控工具,用于性能监控和问题排查. 一.系统性能监控 系统性能工具用于 ...
- (32位)本体学习程序(ontoEnrich)系统配置说明文档
1.系统环境 32位 Ubuntu 源代码中已经包含在32位下编译生成的.o文件,配置好依赖库(步骤2)后,参考步骤3则可重新link. link无误即可运行程序. 2.依赖库 2.1 boost_ ...
- 《JavaScript 实战》:JavaScript 实现拖拽缩放效果
拖拉缩放效果,实现通过鼠标拖动来调整层的面积(宽高)大小,例如选框效果.这里的拖拉缩放比一般的选框复杂一点,能设置八个方位(方向)的固定触发点,能设置最小范围,最大范围和比例缩放. 跟拖放效果一样,程 ...