[原创]python之简单计算器(超详解,只有基本功能+-*/,还有括号处理)
不想看过程的话,直接看文章最后的正式源码
作业需求及分析:
流程图
https://www.processon.com/diagraming/580c5276e4b03c844a5a9716
初期感受
今天10/23,这个作业是我19号拿到的,当时一脸蒙逼,知道么?这里我不可能不可能做出来的感觉!!!
觉得不可能不是没有理由的,
1. 有多括号要怎么区配出最里面那个?? 虽然我前两篇博文有写关与正则表达式的,但还是不会。
2.输入的可是字符串字符串啊
3.如何加减乘除
4.如何先乘除,后加减
实际上遇到比这些还多,但现在就只记起这些……
分析需求:
1.先判断有无括号,无括号直接+-*/
2.有括号先提取出最里面的括号(利用正则表达式)
3.括号外面还有括号怎么办?我这里是用迭代,直到没有括号
4.没有括号,再传给1处理,OK ,搞定
我不会,但我可以去我别人的博客么,但我也看不懂……
妈的,这怎么行!
先写加减乘除,试试吧
1 def mul_mov(s):
2 result = 0
3 if s[1] == '*':
4 result = int(s[0]) * int(s[2])
5 elif s[1] == '/':
6 result = float(s[0]) / int(s[2])
7 result = int(result)
8
9 for i in range(3): # 去掉前三个
10 s.remove(s[0])
11
12 s.insert(0, result) #局部变量引用赋值前的结果
13
14 if len(s) == 1:
15 print(result)
16 else:
17 mul_mov(s)
18
19
20 def main():
21 choose = input("请选择:1.加减;2.乘除")
22 num = input("please input:")
23 if choose == '1':
24 sa = re.split(r'(\D)', num)
25 add_substract(sa)
26 elif choose == '2':
27 sa = re.split(r'(\D)', num)
28 mul_mov(sa)
29
30
31 if __name__=="__main__":
32 main()
但这样肯定还有问题。我当时是这样想的:
#问题:让用户选择1,2不现实,如何让用户输入然后自动加减乘除
#思考:现在已经能够处理,单个的加减或乘除
#可否在混合中先分组出(乘除) eg: ['8+9+','9*4/3','-','4*2‘,‘+5-2’]
#这样可以处理乘除,如何分组呢??
再后来,我卡住了,我回去看我写正则表达式的文章一遍双一遍,还是想不出怎么分组? 感觉太难了,
eg: ['8+9+','9*4/3','-','4*2‘,‘+5-2’] 如何单独的匹配出'9*4/3' ??
PS:如果大神你知道,可以评论和我说下,谢谢!
卡住怎么办?我+-*/乘除都做出来了,肯定不能就此打住的。
于是我打别人的博客看,终于找到一篇我看得懂看得懂的了!!http://www.cnblogs.com/loyfee/p/5764926.html#3538071
参考代码

# coding:utf-8 # 将输入的字符串格式统一转换成列表,将数字、符号、括号都成一个独立元素, # 如: 12+3*(14+5) ----> ["12","+","3","*","(","14","+","5",")"] def format_input(input_re_value): input_re_value = input_re_value.replace(" ","") format_list = [] for i in input_re_value: format_list.append(i) snum = 0 while 1: try: if format_list[snum].isnumeric(): if format_list[snum+1].isnumeric(): format_list[snum] = format_list[snum] + format_list[snum+1] format_list.pop(snum+1) else: snum += 1 else: snum += 1 except IndexError: return format_list break # 计算没有括号的列表的值。 def comput(re_value): while "*" in re_value or "/" in re_value: for i,j in enumerate(re_value): if j == "*": re_cheng = float(re_value[i-1])*float(re_value[i+1]) re_value.pop(i-1) re_value.pop(i-1) re_value.pop(i-1) re_value.insert(i-1,re_cheng) if j == "/": re_chu = float(re_value[i-1])/float(re_value[i+1]) re_value.pop(i-1) re_value.pop(i-1) re_value.pop(i-1) re_value.insert(i-1,re_chu) while "+" in re_value or "-" in re_value: for i,j in enumerate(re_value): if j == "+": re_jia = float(re_value[i-1])+float(re_value[i+1]) re_value.pop(i-1) re_value.pop(i-1) re_value.pop(i-1) re_value.insert(i-1,re_jia) if j == "-": re_jian = float(re_value[i-1])-float(re_value[i+1]) re_value.pop(i-1) re_value.pop(i-1) re_value.pop(i-1) re_value.insert(i-1,re_jian) return re_value[0] # 通过循环,先查找列表的第一个")",然后在")"位置向列表前找到第一个"("所在位置, # 并将其中的元素提取出来,生成新的列表,交给comput计算, # 返回值再插入列表当中,继续循环,直到没有"("为止 def bracket_filter(list1): while "(" in list1: i = list1.index(")") for m in range(i,-1,-1): if list1[m] == "(": list_new = list1[(m+1):i] re_res = comput(list_new) list1.insert(m,str(re_res)) for item1 in range(i+1-m): list1.pop(m+1) break return comput(list1) input_sn = input("pls input:") f_re = format_input(input_sn) result = bracket_filter(f_re) print("The result is:",result)
他思路和我一样一样的。这里他有一个BUG,等下讲。
我得到了启发!可以把输入的字符串分割成列表的一个一个元素。这样就可以解决+-*/的问题了!
接下来就是困惑我最久的括号问题。
在正式讲括号问题前,先看看我自己在这之中调试过一些例子,看下面:
1 s = ["12","pp"]
2 print(s[0].isnumeric()) #True 这里我了解了isnumeric()方法,新技能GET
3 s1 = ["pp","12"]
4 print(s1[0].isnumeric()) #False
5
6 s2 = '1'
7 s3 = '2'
8 s4 = s2 + s3
9 print(s4) #输出12
10
11
12 s5 = "eret67y"
13 s6 = s5[3:6]
14 print(s6) 输出:t67
15
16
17 import re
18 s7 = "5*4-2+((45/3-10*2)-2)"
19 sa = re.split(r'(\D)', s7)
20 print(sa)
21 #['5', '*', '4', '-', '2', '+', '', '(', '', '(', '45', '/', '3', '-', '10', '*', '2', ')', '', '-', '2', ')', '']
22 while True:
23 if "" in sa:
24 sa.remove("") #去掉""
25 else:
26 break
27 print(sa)
28
29 i =7
30 for m in range(i, -1, -1): #start stop step
31 print(m)
32 # 7
33 # 6
34 # 5
35 # 4
36 # 3
37 # 2
38 # 1
39 # 0
40
41 s8 = "(2+(1+(4+5)+9)*2)"
42 s81= "(594)"
43
44
45 s9 = re.split("\((\d+\))",s81)
46 print(s9) #获取括号内数字
47 #['', '594', '']
48 data = re.split(r'\(([^()]+)\)', s8) #我觉得,()在这里是有特殊意义的,代表分组,要单纯表示括号,就得加转义字符
49 print(data) #['(2+(1+', '4+5', '+9)*2)']
50
51
52 s10 = "abdcdeff"
53 s11 = re.search("[^cd]+", s10) #天呐!不是非c或d,而是非c且非d
54 print(s11) #<_sre.SRE_Match object; span=(0, 2), match='ab'>
55
56
57 s12 = len("re")
58 print(s12) #2
59
60
61 re_str = "3455454+97"
62 if "+" not in re_str and "-" not in re_str and "*" not in re_str \
63 and "/" not in re_str and "(" not in re_str and ")" not in re_str:
64 print("AA")
65 else:
66 print("BB")
67
68 num = 50/2
69 print(num) #25.0 #有小数点,这里我也蒙比了!等一下讲。
70 num1 = 50 * 2
71 print(num1)
上面的懂了之后,我开始搞代码了
一、字符串分割为列表元素
# 将输入的字符串格式统一转换成列表,将数字、符号、括号都成一个独立元素,
# 如: 12+3*(14+5) ----> ["12","+","3","*","(","14","+","5",")"]
def format_input(input_re_value):
input_re_value = input_re_value.replace(" ", "") #去掉输入的空格
input_re_value = re.split(r'(\D)', input_re_value)
while True:
if "" in input_re_value:
input_re_value.remove("") #将列表中""去掉
else:
break
return input_re_value
这里用了正则表达式的split(),不大懂的可以看我前面的博文,format_input()传入一个字符串,返回一个列表。
二、+-*/

# 计算没有括号的列表的值。加减乘除 def comput(re_value): while "*" in re_value or "/" in re_value: for i, j in enumerate(re_value): if j == "*": re_cheng = int(re_value[i - 1]) * int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_cheng) break if j == "/": re_chu = int(re_value[i - 1]) / int(re_value[i + 1]) re_chu = int(re_chu) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_chu) break while "+" in re_value or "-" in re_value: for i, j in enumerate(re_value): if j == "+": re_jia = int(re_value[i - 1]) + int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_jia) print("re_jia",re_jia) print("re_value",re_value) break if j == "-": re_jian = int(re_value[i - 1]) - int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_jian) print(re_jian) print(re_value) break return re_value[0]
这里有一个坑,就是我前面说参考别人的博文,但是他写的有一个BUG,有兴趣可以研究下。这上面的代码是我改正过的。
三、括号处理
这里不贴代码,下面源码有。就说下我的思路:
如果输入的有括号的话: 1.用li = re.split(r'\(([^()]+)\)', input_str)将其折分
2.data = re.search(r'\(([^()]+)\)', input_str).group() 取出最里面括号的数(包括())
3.去除括号,找出最里面括号的数的下标,最后进行替换。
4.还有括号的话,进行迭代,直到无括号
调试代码:

import re import sys # 将输入的字符串格式统一转换成列表,将数字、符号、括号都成一个独立元素, # 如: 12+3*(14+5) ----> ["12","+","3","*","(","14","+","5",")"] def format_input(input_re_value): input_re_value = input_re_value.replace(" ", "") #去掉输入的空格 input_re_value = re.split(r'(\D)', input_re_value) while True: if "" in input_re_value: input_re_value.remove("") #将列表中""去掉 else: break return input_re_value # 计算没有括号的列表的值。加减乘除 def comput(re_value): while "*" in re_value or "/" in re_value: for i, j in enumerate(re_value): if j == "*": re_cheng = int(re_value[i - 1]) * int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_cheng) break if j == "/": re_chu = int(re_value[i - 1]) / int(re_value[i + 1]) re_chu = int(re_chu) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_chu) break while "+" in re_value or "-" in re_value: for i, j in enumerate(re_value): if j == "+": re_jia = int(re_value[i - 1]) + int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_jia) print("re_jia",re_jia) print("re_value",re_value) break if j == "-": re_jian = int(re_value[i - 1]) - int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_jian) print(re_jian) print(re_value) break return re_value[0] def bracket(input_str): if not re.search(r'\(([^()]+)\)', input_str): #若没有括号 s = format_input(input_str) print("s_format",s) print("comput(s)",comput(s)) return comput(s) else: #有括号 li = re.split(r'\(([^()]+)\)', input_str) print("li:",li) #['(', '9+8', '-8)'] 输入((9+8)-8) data = re.search(r'\(([^()]+)\)', input_str).group() print("data:",data) # 输出:(9+8) data_strip = data.strip("()") print("data_strip:",data_strip) #9+8 inde = li.index(data_strip) #取得其下标 print("index:",inde) # 1 ret = comput(format_input(data_strip)) #参数为列表形式 print("ret:",ret) #17.0 # 如何把小括号计算后再替换进去 li.pop(inde) li.insert(inde, str(ret)) print("li:",li) #['(', '17.0', '-8)'] re_str = "".join(li) print("re_str",re_str) #(17.0-8) if "+" not in re_str and "-" not in re_str and "*" not in re_str \ and "/" not in re_str and "(" not in re_str and ")" not in re_str: print("有没有return ",re_str) return re_str #为什么没有return else: return bracket(re_str) #迭代 if __name__ == '__main__': while True: input_str = input("please input(q=quit):") if input_str.strip() == "": continue elif input_str == 'q' or input_str == 'quit': sys.exit() else: bracket_reture = bracket(input_str) print("result:",bracket_reture,type(bracket_reture))
调试实例:

C:\Python34\python3.exe C:/Users/Administrator/PycharmProjects/laonanhai/day6_test/test1.py please input(q=quit):12+45-85+2 s_format ['12', '+', '45', '-', '85', '+', '2'] re_jia 57 re_value [57, '-', '85', '+', '2'] -28 [-28, '+', '2'] re_jia -26 re_value [-26] comput(s) -26 result: -26 <class 'int'> please input(q=quit): please input(q=quit): please input(q=quit):(((9+9)-6)+45)+45/3*2 li: ['((', '9+9', '-6)+45)+45/3*2'] data: (9+9) data_strip: 9+9 index: 1 re_jia 18 re_value [18] ret: 18 li: ['((', '18', '-6)+45)+45/3*2'] re_str ((18-6)+45)+45/3*2 li: ['(', '18-6', '+45)+45/3*2'] data: (18-6) data_strip: 18-6 index: 1 12 [12] ret: 12 li: ['(', '12', '+45)+45/3*2'] re_str (12+45)+45/3*2 li: ['', '12+45', '+45/3*2'] data: (12+45) data_strip: 12+45 index: 1 re_jia 57 re_value [57] ret: 57 li: ['', '57', '+45/3*2'] re_str 57+45/3*2 s_format ['57', '+', '45', '/', '3', '*', '2'] re_jia 87 re_value [87] comput(s) 87 result: 87 <class 'int'> please input(q=quit):q Process finished with exit code 0
正式源码:

import re import sys # 将输入的字符串格式统一转换成列表,将数字、符号、括号都成一个独立元素, # 如: 12+3*(14+5) ----> ["12","+","3","*","(","14","+","5",")"] def format_input(input_re_value): input_re_value = input_re_value.replace(" ", "") #去掉输入的空格 input_re_value = re.split(r'(\D)', input_re_value) while True: if "" in input_re_value: input_re_value.remove("") #将列表中""去掉 else: break return input_re_value # 计算没有括号的列表的值。加减乘除 def comput(re_value): while "*" in re_value or "/" in re_value: for i, j in enumerate(re_value): if j == "*": re_cheng = int(re_value[i - 1]) * int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_cheng) break if j == "/": re_chu = int(re_value[i - 1]) / int(re_value[i + 1]) re_chu = int(re_chu) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_chu) break while "+" in re_value or "-" in re_value: for i, j in enumerate(re_value): if j == "+": re_jia = int(re_value[i - 1]) + int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_jia) break if j == "-": re_jian = int(re_value[i - 1]) - int(re_value[i + 1]) re_value.pop(i - 1) re_value.pop(i - 1) re_value.pop(i - 1) re_value.insert(i - 1, re_jian) break return re_value[0] def bracket(input_str): if not re.search(r'\(([^()]+)\)', input_str): #若没有括号 s = format_input(input_str) return comput(s) else: #有括号 li = re.split(r'\(([^()]+)\)', input_str) data = re.search(r'\(([^()]+)\)', input_str).group() data_strip = data.strip("()") inde = li.index(data_strip) #取得其下标 ret = comput(format_input(data_strip)) #参数为列表形式 li.pop(inde) li.insert(inde, str(ret)) re_str = "".join(li) if "+" not in re_str and "-" not in re_str and "*" not in re_str \ and "/" not in re_str and "(" not in re_str and ")" not in re_str: return re_str #为什么没有return else: return bracket(re_str) #迭代 if __name__ == '__main__': while True: input_str = input("please input(q=quit):") if input_str.strip() == "": continue elif input_str == 'q' or input_str == 'quit': sys.exit() else: bracket_reture = bracket(input_str) print("result:",bracket_reture)
输出源码:

C:\Python34\python3.exe C:/Users/Administrator/PycharmProjects/laonanhai/day6_test/fina_howo.py please input(q=quit):50+48*82/2 result: 2018 please input(q=quit):100+15 result: 115 please input(q=quit):(((9+9)-9)+9) result: 18 please input(q=quit):15/3*2*8/4 result: 20 please input(q=quit): Process finished with exit code 1
欢迎转发!
This is zcl‘s article! Thanks for your support!
文章出处:http://www.cnblogs.com/0zcl
作者:zcl
出处:http://www.cnblogs.com/0zcl
文章未标明转载则为原创博客。欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
1.非系统的学习也是在浪费时间
2.做一个会欣赏美,懂艺术,会艺术的技术人
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?