生活不易,缅怀一下python课设,帮助下一个有缘人
注意:里面有两个python计算器的代码,从高阶到低阶应有尽有
第一个计算器功能:
实现简单的加减乘除,支持小数点和负数运算
实现复合运算和取余运算
实现sin,arcsin,ln,平方根,以及幂的运算
实现十进制到二进制转换
实现e,π的输出
可以复制粘贴剪切计算器中的数据
可以全部清除和只清除一个
计算器样式
代码
calculate.py
importrefrommathimport*#将算式从字符串处理成列表,解决横杠是负号还是减号的问题defformula_format(formula):"""解释参数类型:paramformula:str"""formula=re.sub('','',formula)#re.sub()在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串#去掉算式中的空格s#以'横杠数字'分割,其中正则表达式:(\-\d\.?\d*)括号内:#\-表示匹配横杠开头;\d表示匹配数字1次或多次;\.?表示匹配小数点0次或1次;\d*表示匹配数字0次或多次。#[]中的字符是任选择一个使用,括号(…)可以把(…)看出一个整体,经常与""、"*"、"?"的连续使用,对(…)部分进行重复.formula_list=[iforiinre.split('(\-[\d,π,e]\.?\d*)',formula)ifi]#re.split()将一个字符串按照正则表达式匹配结果进行分割,返回列表类型final_formula=[]#最终的算式列表foriteminformula_list:#算式以横杠开头,则第一个数字为负数,横杠为负号#re.match()从一个字符串的开始位置起匹配正则表达式,返回match对象#如果不是起始位置匹配成功的话,match()就返回none#$字符比配字符串的结尾位置iflen(final_formula)==0andre.match('\-[\d,π,e]\.?\d*$',item):final_formula.append(item)continue#如果当前的算式列表最后一个元素的第一个位置是运算符['','-','*','/','(','%','^'],#则横杠为减号iflen(final_formula)>0:#输出为none或者数字ifre.match('[\\-\*\/\(\%\^]$',final_formula[-1]):final_formula.append(item)continue#按照运算符分割开item_split=[iforiinre.split('([\\-\*\/\(\)\%\^\√])',item)ifi]final_formula=item_splitreturnfinal_formula#判断是否是运算符,如果是返回Truedefis_operator(e):""":parame:str:return:bool"""opers=['','-','*','/','(',')','%','^','√','sin','arcsin','ln']returnTrueifeinoperselseFalse#在for循环中嵌套使用if和else语句#比较连续两个运算符来判断是压栈还是弹栈defdecision(tail_op,now_op):""":paramtail_op:运算符栈的最后一个运算符:paramnow_op:从算式列表取出的当前运算符:return:1代表弹栈运算,0代表弹出运算符栈最后一个元素'(',-1表示压栈"""#定义4种运算符级别rate1=['','-']rate2=['*','/','%']rate3=['^','√','sin','arcsin','ln']rate4=['(']rate5=[')']iftail_opinrate1:ifnow_opinrate2ornow_opinrate3ornow_opinrate4:return-1#说明当前运算符优先级高于运算符栈的最后一个运算符,需要压栈else:return1#说明当前运算符优先级等于运算符栈的最后一个运算符,需要弹栈运算eliftail_opinrate2:ifnow_opinrate3ornow_opinrate4:return-1else:return1eliftail_opinrate3:ifnow_opinrate4:return-1else:return1eliftail_opinrate4:ifnow_opinrate5:return0#'('遇上')',需要弹出'('并丢掉')',表明该括号内的算式已计算完成并将结果压入数字栈中else:return-1#只要栈顶元素为'('且当前元素不是')',都应压入栈中#传入两个数字,一个运算符,根据运算符不同返回相应结果defcalculate(n1,n2,operator):""":paramn1:float:paramn2:float:paramoperator:-*/%^:return:float"""result=0ifoperator=='':result=n1n2ifoperator=='-':result=n1-n2ifoperator=='*':result=n1*n2ifoperator=='/':result=n1/n2ifoperator=='%':result=n1%n2ifoperator=='^':result=n1**n2returnresult#括号内的算式求出计算结果后,计算√ ̄()、sin()或arcsin()defgaojie(op_stack,num_stack):#运算符栈,数字栈ifop_stack[-1]=='√':#pop()函数用于移除列表中的一个元素(默认最后一个元素),并且返回从列表中移除的元素对象。#append()函数可以向列表末尾添加元素op=op_stack.pop()num2=num_stack.pop()num_stack.append(sqrt(num2))elifop_stack[-1]=='sin':op=op_stack.pop()num2=num_stack.pop()num_stack.append(sin(num2))elifop_stack[-1]=='arcsin':op=op_stack.pop()num2=num_stack.pop()num_stack.append(asin(num2))elifop_stack[-1]=='ln':op=op_stack.pop()num2=num_stack.pop()num_stack.append(log(num2))#负责遍历算式列表中的字符,决定压入数字栈中或压入运算符栈中或弹栈运算deffinal_calc(formula_list):""":paramformula_list:算式列表:return:计算结果"""num_stack=[]#数字栈op_stack=[]#运算符栈foriteminformula_list:operator=is_operator(item)#压入数字栈ifnotoperator:#π和e转换成可用于计算的值ifitem=='π':num_stack.append(pi)elifitem=='-π':num_stack.append(-pi)elifitem=='e':num_stack.append(e)elifitem=='-e':num_stack.append(-e)else:num_stack.append(float(item))#字符串转换为浮点数#如果是运算符else:whileTrue:#如果运算符栈为空,则无条件入栈iflen(op_stack)==0:op_stack.append(item)break#决定压栈或弹栈tag=decision(op_stack[-1],item)#如果是-1,则压入运算符栈并进入下一次循环iftag==-1:op_stack.append(item)break#如果是0,则弹出运算符栈内最后一个'('并丢掉当前')',进入下一次循环eliftag==0:op_stack.pop()#'('前是'√ ̄'、'sin'或'arcsin'时,对括号内算式的计算结果作相应的运算gaojie(op_stack,num_stack)break#如果是1,则弹出运算符栈内最后一个元素和数字栈内最后两个元素eliftag==1:ifitemin['√','sin','arcsin']:op_stack.append(item)breakop=op_stack.pop()num2=num_stack.pop()num1=num_stack.pop()#将计算结果压入数字栈并接着循环,直到遇到break跳出循环num_stack.append(calculate(num1,num2,op))#大循环结束后,数字栈和运算符栈中可能还有元素的情况whilelen(op_stack)!=0:op=op_stack.pop()num2=num_stack.pop()num1=num_stack.pop()num_stack.append(calculate(num1,num2,op))result=str(num_stack[0])#去掉无效的0和小数点,例:1.0转换为1ifresult[len(result)-1]=='0'andresult[len(result)-2]=='.':result=result[0:-2]returnresultif__name__=='__main__':#formula="2*(3-5*(-63*2/2))"formula="e"formula_list=formula_format(formula)result=final_calc(formula_list)print("算式:",formula)print("计算结果:",result)Calculator.py
fromtkinterimport*fromfunctoolsimportpartial#partial()函数允许你给一个或多个参数设置固定的值,减少接下来被调用时的参数个数。fromcalculateimport*#生成计算器主界面defbuju(root):menu=Menu(root)#创建主菜单#新建一个空的菜单,将原menu菜单的menu属性指定为submune1,即filemenu1为menu的下拉菜单#tearoff属性:通常情况下,菜单可以被撕掉,第一个位置(位置0)在选择列表中被删除元素占据#并且额外的选择从位置1开始。#如果设置了tearoff=0,菜单将不会有一个tearoff特性,并且选择将从位置0开始添加。submenu1=Menu(menu,tearoff=0)#分窗,0为在原窗,1为点击分为两个窗口#add_cascade()方法:通过将给定的菜单与父菜单相关联,创建一个新的分层菜单。menu.add_cascade(label='编辑',menu=submenu1)#添加子选项(label参数为显示内容)#add_command(options)方法:将菜单项添加到菜单中。submenu1.add_command(#创建了一个名为“XX”的标签,按下后执行bianji/编辑函数,label='复制',command=lambda:bianji(entry,'copy'))#添加命令submenu1.add_command(label='剪切',command=lambda:bianji(entry,'cut'))submenu1.add_command(label='粘贴',command=lambda:bianji(entry,'paste'))submenu2=Menu(menu,tearoff=0)menu.add_cascade(label='查看',menu=submenu2)submenu2.add_command(label='帮助',command=lambda:chakan(entry,'help'))submenu2.add_command(label='作者',command=lambda:chakan(entry,'author'))root.config(menu=menu)#重新配置,添加菜单label=Label(root,width=36,height=1,bd=5,bg='white',anchor='se',textvariable=label_text)#标签,可以显示文字或图片label.grid(row=0,columnspan=5)#布局器,向窗口注册并显示控件#rowspan:设置单元格纵向跨越的列数#Entry(根对象,[属性列表]),实现添加输入框,width设置显示宽度#bd设置按钮的边框大小,bg设置背景色,front设置字体及大小#justify设置多行文本的对其方式entry=Entry(root,width=23,bd=5,bg='white',justify="right",font=('微软雅黑',12))#文本框(单行)entry.grid(row=1,column=0,columnspan=5,sticky=NWSE,padx=5,pady=5)#设置控件周围x、y方向空白区域保留大小#cursor为鼠标悬停光标myButton=partial(Button,root,width=5,cursor='hand2',activebackground='#90EE90')#偏函数:带有固定参数的函数button_sin=myButton(text='sin',command=lambda:get_input(entry,'sin('))#按钮button_arcsin=myButton(text='arcsin',command=lambda:get_input(entry,'arcsin('))button_exp=myButton(text='e',command=lambda:get_input(entry,'e'))button_ln=myButton(text='ln',command=lambda:get_input(entry,'ln('))button_xy=myButton(text='x^y',command=lambda:get_input(entry,'^'))button_sin.grid(row=2,column=0)button_arcsin.grid(row=2,column=1)button_exp.grid(row=2,column=2)button_ln.grid(row=2,column=3)button_xy.grid(row=2,column=4)button_shanyige=myButton(text='←',command=lambda:backspace(entry))#command指定按钮消息的回调函数button_shanquanbu=myButton(text='C',command=lambda:clear(entry))button_zuokuohao=myButton(text='(',command=lambda:get_input(entry,'('))button_youkuohao=myButton(text=')',command=lambda:get_input(entry,')'))button_genhao=myButton(text='√x',command=lambda:get_input(entry,'√('))button_shanyige.grid(row=3,column=0)button_shanquanbu.grid(row=3,column=1)button_zuokuohao.grid(row=3,column=2)button_youkuohao.grid(row=3,column=3)button_genhao.grid(row=3,column=4)button_7=myButton(text='7',command=lambda:get_input(entry,'7'))button_8=myButton(text='8',command=lambda:get_input(entry,'8'))button_9=myButton(text='9',command=lambda:get_input(entry,'9'))button_chu=myButton(text='/',command=lambda:get_input(entry,'/'))button_yu=myButton(text='%',command=lambda:get_input(entry,'%'))button_7.grid(row=4,column=0)button_8.grid(row=4,column=1)button_9.grid(row=4,column=2)button_chu.grid(row=4,column=3)button_yu.grid(row=4,column=4)button_4=myButton(text='4',command=lambda:get_input(entry,'4'))button_5=myButton(text='5',command=lambda:get_input(entry,'5'))button_6=myButton(text='6',command=lambda:get_input(entry,'6'))button_cheng=myButton(text='*',command=lambda:get_input(entry,'*'))button_jiecheng=myButton(text='二进制',command=lambda:jinzhi(entry))button_4.grid(row=5,column=0)button_5.grid(row=5,column=1)button_6.grid(row=5,column=2)button_cheng.grid(row=5,column=3)button_jiecheng.grid(row=5,column=4)button_1=myButton(text='1',command=lambda:get_input(entry,'1'))button_2=myButton(text='2',command=lambda:get_input(entry,'2'))button_3=myButton(text='3',command=lambda:get_input(entry,'3'))button_jian=myButton(text='-',command=lambda:get_input(entry,'-'))button_dengyu=myButton(text='\n=\n',command=lambda:calculator(entry))button_1.grid(row=6,column=0)button_2.grid(row=6,column=1)button_3.grid(row=6,column=2)button_jian.grid(row=6,column=3)button_dengyu.grid(row=6,column=4,rowspan=2)#rowspan:设置单元格横向跨越的行数button_pai=myButton(text='π',command=lambda:get_input(entry,'π'))button_0=myButton(text='0',command=lambda:get_input(entry,'0'))button_xiaoshudian=myButton(text='.',command=lambda:get_input(entry,'.'))button_jia=myButton(text='',command=lambda:get_input(entry,''))button_pai.grid(row=7,column=0)button_0.grid(row=7,column=1)button_xiaoshudian.grid(row=7,column=2)button_jia.grid(row=7,column=3)#对文本框中的算式或答案进行复制、剪切或粘贴defbianji(entry,argu):""":paramentry:文本框:paramargu:按钮对应的值"""ifargu=='copy':entry.event_generate("<<Copy>>")elifargu=='cut':entry.event_generate("<<Cut>>")clear(entry)elifargu=='paste':entry.event_generate("<<Paste>>")#查看使用帮助和作者信息defchakan(entry,argu):root=Tk()root.resizable(0,0)text=Text(root,width=20,height=2,bd=5,bg='#FFFACD',font=('微软雅黑',12))text.grid(padx=5,pady=5)ifargu=='help':root.title('帮助')text.insert(INSERT,'哈你的希望落空了吧\n')text.insert(INSERT,'这里可没有帮助')elifargu=='author':root.title('作者')text.insert(INSERT,'Author:许许\n')text.insert(INSERT,'Time:2022.06.17')#删除最后一次输入内容defbackspace(entry):entry.delete(len(entry.get())-1)#删除文本框的最后一个输入值#删除所有输入内容和显示内容defclear(entry):entry.delete(0,END)#删除文本框的所有内容label_text.set('')#点击计算器输入按钮后向文本框中添加内容defget_input(entry,argu):formula=entry.get()forcharinformula:if'\u4e00'<=char<='\u9fa5':clear(entry)#删除文本框中的汉字显示,减少手动删除操作entry.insert(INSERT,argu)#使用END时,键盘敲入和按键输入组合操作会出错#十进制整数转换为二进制整数defjinzhi(entry):try:formula=entry.get()ifre.match('\d$',formula):number=int(formula)cunchu=[]#放置每次除以2后的余数result=''whilenumber:cunchu.append(number%2)number//=2#整数除法,返回商whilecunchu:result=str(cunchu.pop())#将所有余数倒置得到结果clear(entry)entry.insert(END,result)label_text.set(''.join(formula'='))else:clear(entry)entry.insert(END,'请输入十进制整数')except:clear(entry)entry.insert(END,'出错')#点击“=”后进行计算defcalculator(entry):try:formula=entry.get()#输入内容只是数字或π或e时,仍显示该内容ifre.match('-?[\d,π,e]\.?\d*$',formula):label_text.set(''.join(formula'='))return#输入内容是算式时,显示其计算结果result=final_calc(formula_format(formula))clear(entry)entry.insert(END,result)#将结果输出到文本框中label_text.set(''.join(formula'='))except:clear(entry)entry.insert(END,'出错')if__name__=='__main__':root=Tk()#生成窗口root.title('简易计算器')#窗口的名字root.resizable(0,0)#窗口大小可调性,分别表示x,y方向的可变性globallabel_text#定义全局变量label_text=StringVar()buju(root)root.mainloop()#进入消息循环(必需组件),否则生成的窗口一闪而过注:这个代码我能说的都在备注里
第二个计算器:
实现简单的加减乘除,支持小数点和负数运算
实现复合运算和取余运算
可以全部清除和只清除一个
计算机样式
代码:
calculate1.py
importtkinterimporttkinter.fontclassCalculator(object):def__init__(self):self.all_press_lists=[]self.is_press=Falseself.is_press_num=Falseself.root=tkinter.Tk()self.result=tkinter.StringVar()#显示输入的数字及结果self.record=tkinter.StringVar()#显示计算过程defmain(self):self.root.minsize(300,550)self.root.title('计算器')input_bg="#393943"num_fg="#DCDCDC"btn_fg="#909194"btn_bg="#22222C"btn_w=75btn_h=70my_font=tkinter.font.Font(family='微软雅黑',size=20)#设置字体self.result.set(0)self.record.set('')#显示版label=tkinter.Label(self.root,font=my_font,bg=input_bg,bd='9',fg=num_fg,anchor='se',textvariable=self.record)label.place(width=300,height=120)label2=tkinter.Label(self.root,font=my_font,bg=input_bg,bd='9',fg=num_fg,anchor='se',textvariable=self.result)label2.place(y=120,width=300,height=80)#第一行btn_ac=tkinter.Button(self.root,text='c',font=my_font,bg=btn_bg,fg=btn_fg,bd=0,command=lambda:self.press_compute('AC'))btn_ac.place(x=btn_w*0,y=200btn_h*0,width=btn_w,height=btn_h)btn_back=tkinter.Button(self.root,text='←',font=my_font,bg=btn_bg,fg=btn_fg,bd=0,command=lambda:self.press_compute('b'))btn_back.place(x=btn_w*1,y=200btn_h*0,width=btn_w,height=btn_h)btn_per=tkinter.Button(self.root,text='%',font=my_font,bg=btn_bg,fg=btn_fg,bd=0,command=lambda:self.press_compute('%'))btn_per.place(x=btn_w*2,y=200btn_h*0,width=btn_w,height=btn_h)btn_divi=tkinter.Button(self.root,text='÷',font=my_font,bg=btn_bg,fg=btn_fg,bd=0,command=lambda:self.press_compute('/'))btn_divi.place(x=btn_w*3,y=200btn_h*0,width=btn_w,height=btn_h)#第二行btn7=tkinter.Button(self.root,text='7',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('7'))btn7.place(x=btn_w*0,y=200btn_h*1,width=btn_w,height=btn_h)btn8=tkinter.Button(self.root,text='8',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('8'))btn8.place(x=btn_w*1,y=200btn_h*1,width=btn_w,height=btn_h)btn9=tkinter.Button(self.root,text='9',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('9'))btn9.place(x=btn_w*2,y=200btn_h*1,width=btn_w,height=btn_h)btn_mul=tkinter.Button(self.root,text='×',font=my_font,bg=btn_bg,fg=btn_fg,bd=0,command=lambda:self.press_compute('*'))btn_mul.place(x=btn_w*3,y=200btn_h*1,width=btn_w,height=btn_h)#第三行btn4=tkinter.Button(self.root,text='4',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('4'))btn4.place(x=btn_w*0,y=200btn_h*2,width=btn_w,height=btn_h)btn5=tkinter.Button(self.root,text='5',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('5'))btn5.place(x=btn_w*1,y=200btn_h*2,width=btn_w,height=btn_h)btn6=tkinter.Button(self.root,text='6',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('6'))btn6.place(x=btn_w*2,y=200btn_h*2,width=btn_w,height=btn_h)btn_sub=tkinter.Button(self.root,text='-',font=my_font,bg=btn_bg,fg=btn_fg,bd=0,command=lambda:self.press_compute('-'))btn_sub.place(x=btn_w*3,y=200btn_h*2,width=btn_w,height=btn_h)#第四行btn1=tkinter.Button(self.root,text='1',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('1'))btn1.place(x=btn_w*0,y=200btn_h*3,width=btn_w,height=btn_h)btn2=tkinter.Button(self.root,text='2',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('2'))btn2.place(x=btn_w*1,y=200btn_h*3,width=btn_w,height=btn_h)btn3=tkinter.Button(self.root,text='3',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('3'))btn3.place(x=btn_w*2,y=200btn_h*3,width=btn_w,height=btn_h)btn_add=tkinter.Button(self.root,text='',font=my_font,bg=btn_bg,fg=btn_fg,bd=0,command=lambda:self.press_compute(''))btn_add.place(x=btn_w*3,y=200btn_h*3,width=btn_w,height=btn_h)#第五行btn0=tkinter.Button(self.root,text='0',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('0'))btn0.place(x=btn_w*0,y=200btn_h*4,width=btn_w*2,height=btn_h)btn_point=tkinter.Button(self.root,text='.',font=my_font,bg=btn_bg,fg=num_fg,bd=0,command=lambda:self.press_num('.'))btn_point.place(x=btn_w*2,y=200btn_h*4,width=btn_w,height=btn_h)btn_equ=tkinter.Button(self.root,text='=',bg='#982425',font=my_font,fg=num_fg,bd=0,command=lambda:self.press_equal())btn_equ.place(x=btn_w*3,y=200btn_h*4,width=btn_w,height=btn_h)self.root.mainloop()#按下数字键defpress_num(self,num):ifself.is_pressisFalse:passelse:self.result.set(0)self.is_press=False#判断界面的数字是否为0old_num=self.result.get()ifold_num=='0':self.result.set(num)else:new_num=old_numnumself.result.set(new_num)#按下运算键defpress_compute(self,sign):num=self.result.get()self.all_press_lists.append(num)self.all_press_lists.append(sign)self.is_press=Trueifsign=='AC':#按下'AC',清空列表内容,显示0self.all_press_lists.clear()self.result.set(0)ifsign=='b':#按下退格,当前数字逐步减一a=num[0:-1]self.all_press_lists.clear()self.result.set(a)#获取运算结果函数defpress_equal(self):cur_num=self.result.get()self.all_press_lists.append(cur_num)compute_str=''.join(self.all_press_lists)try:calculate_result=eval(compute_str)except:calculate_result='badparameter'self.result.set(calculate_result)#显示结果self.record.set(compute_str"=")#显示运算过程self.all_press_lists.clear()#清空列表内容if__name__=='__main__':my_calculator=Calculator()my_calculator.main()虽然但是其实我还有两个计算器的代码,太长了就不发了,我只是一个平平无奇的搬运工,要是想要可以私信我