20191331刘宇轩 《python公选课》实验二

20191331刘宇轩 《Python程序设计》实验二报告


课程:《Python程序设计》
班级: 1913
姓名: 刘宇轩
学号:20191331
实验教师:王志强
实验日期:2021年5月7日
必修/选修: 公选课


1. 实验内容

  • 设计并完成一个完整的应用程序,完成加减乘除模等运算,功能多多益善。
  • 考核基本语法、判定语句、循环语句、逻辑运算等知识点

2. 实验要求

  • 创建工程项目,使用Python语言实现具体的操作运算,并完成程序调试和运行,代码托管到码云。

3.实验过程及结果

  1. 对于一个计算器,其拥有的功能很重要。首先要实现加减乘除、求模和幂函数这几个简单功能。

代码如下

def add(a, b):
   return a + b
def minus(a, b):
   return a - b
def mul(a, b):
   return a * b
def div(a, b):
   if b == 0:
       print("Error")
   else:
       return a / b
def mod(a, b):
   return a % b
def power(a, b):
   return a ** b
print("1:加法 2:减法 3:乘法 4:除法 5:求模 6:幂运算
")
s = int(input("请输入运算方法:"))
n1 = float(input("请输入第一个数:"))
n2 = float(input("请输入第二个数:"))
print("结果为:")
   if s == 1:
       print(add(n1, n2))
   if s == 2:
       print(minus(n1, n2))
   if s == 3:
       print(mul(n1, n2))
   if s == 4:
       print(div(n1, n2))
   if s == 5:
       print(mod(n1, n2))
   if s == 6:
       print(power(n1, n2))

一个拥有基本功能的计算器完成了。

  1. 在实现计算器的基本功能后,我想让计算器可以一次处理多个数,查找后发现可以使用eval()函数来进行运算。

代码如下

# 表达式运算
def test(date):
   result = eval(date)
   return result
print("支持加减乘除和求模(%)与幂函数(**)
示例:(8+7)%3**4")
m = input("请输入表达式:")
print("结果为:", test(m))
  1. 继续添加开方,三角函数,对数运算,最大公约数,向下取整这些功能,幸好python中math库中有这些功能,只需引入Python中的math函数库,便能实现我想要的功能,非常easy。

代码如下

import math
s = int(input("请输入运算方法:"))
if s == 1:
   print("对数运算")
   n3 = float(input("请输入运算数:"))
   n4 = float(input("请输入底数:"))
   print("结果为:", math.log(n3, n4))
elif s == 10:
   print("最大公约数")
   n5 = float(input("请输入第一个运算数:"))
   n6 = float(input("请输入第二个运算数:"))
   print("结果为:", math.gcd(n5, n6))
elif 2 <= s <= 9:
   n7 = float(input("请输入运算数(三角函数仅输入弧度制pi前的系数):"))
   if s == 2:
       print("开方运算
结果为:", math.sqrt(n7))
   if s == 3:
       print("向下取整
结果为:", math.trunc(n7))
   if s == 4:
       print("向上取整
结果为:", math.ceil(n7))
   if s == 5:
       print("弧度转换角度
结果为:", math.degrees(n7))
   if s == 6:
       print("角度转换弧度
结果为:", math.radians(n7))
   if s == 7:
       print("正弦函数
结果为:", math.sin(math.pi*n7))
   if s == 8:
       print("余弦函数
结果为:", math.cos(math.pi*n7))
   if s == 9:
       print("正切函数
结果为:", math.tan(math.pi*n7))
  1. 所需功能均已实现,接下来就是整合到一起了,使用while循环实现计算器的多次使用,再用if语句进行功能选择。
    当需要退出时使用break
   elif i == 0:
      break

代码如下

while True:
    print("计算器")
    i = int(input("基本运算输1,表达式运算输2,高级功能输3,输0退出
请输入:"))
    if i == 1:
        print("1:加法 2:减法 3:乘法 4:除法 5:求模 6:幂运算
")
        s = int(input("请输入运算方法:"))
        n1 = float(input("请输入第一个数:"))
        n2 = float(input("请输入第二个数:"))
        print("结果为:")
        if s == 1:
            print(add(n1, n2))
        if s == 2:
            print(minus(n1, n2))
        if s == 3:
            print(mul(n1, n2))
        if s == 4:
            print(div(n1, n2))
        if s == 5:
            print(mod(n1, n2))
        if s == 6:
            print(power(n1, n2))
    elif i == 2:
        print("支持加减乘除和求模(%)与幂函数(**)
示例:3+4-(3-2)**2")
        m = input("请输入表达式:")
        print("结果为:", test(m))
    elif i == 3:
        print("1:对数函数 2:开方 3:向下取整 4:向上取整 5:弧度转换角度 6:角度转换弧度 7:正弦函数 8:余弦函数 9:正切函数 10:最大公约数")
        s = int(input("请输入运算方法:"))
        if s == 1:
            print("对数运算")
            n3 = float(input("请输入运算数:"))
            n4 = float(input("请输入底数:"))
            print("结果为:", math.log(n3, n4))
        elif s == 10:
            print("最大公约数")
            n5 = float(input("请输入第一个运算数:"))
            n6 = float(input("请输入第二个运算数:"))
            print("结果为:", math.gcd(n5, n6))
        elif 2 <= s <= 9:
            n7 = float(input("请输入运算数(三角函数仅输入弧度制pi前的系数):"))
            if s == 2:
                print("开方运算
结果为:", math.sqrt(n7))
            if s == 3:
                print("向下取整
结果为:", math.trunc(n7))
            if s == 4:
                print("向上取整
结果为:", math.ceil(n7))
            if s == 5:
                print("弧度转换角度
结果为:", math.degrees(n7))
            if s == 6:
                print("角度转换弧度
结果为:", math.radians(n7))
            if s == 7:
                print("正弦函数
结果为:", math.sin(math.pi*n7))
            if s == 8:
                print("余弦函数
结果为:", math.cos(math.pi*n7))
            if s == 9:
                print("正切函数
结果为:", math.tan(math.pi*n7))
    elif i == 0:
        break
  1. 在cmd界面运行计算器既不美观也不方便,每一次运算命令都要手动输入选择,十分的不方便,所以参照上学期计算机实习时制作GUI界面时的经验,为计算器进行GUI界面设计,将所有操作替换为鼠标按钮设计,这样既美观又方便。实践过程中python的GUI设计比较简单,引入tkinter库后只需合理分配窗口化大小,和按钮位置,就能制作简单的GUI计算器界面。

GUI代码如下

'''
作者:刘宇轩
文件名称:计算器GUI
时间:2021.5.7
'''

import tkinter as tk
from tkinter import ttk
import math


def get(entry, argu):
    indata = entry.get()
    if (indata[-1:] == '+') and (argu in ['+', '*', '/', '%', '**']):
        return
    if (indata[-1:] == '-') and (argu in ['+', '*', '/', '%', '**']):
        return
    if (indata[-1:] == '*') and (argu in ['+', '/', '%', '**']):
        return
    if (indata[-1:] == '/') and (argu in ['+', '*', '%', '**']):
        return
    if (indata[-1:] == '&') and (argu in ['+', '*', '/', '%', '**']):
        return
    if (indata[-2:] == '+-') and (argu in ['+', '-', '*', '/', '%', '**']):
        return
    if (indata[-2:] == '--') and (argu in ['+', '-', '*', '/', '%', '**']):
        return
    if (indata[-2:] == '**') and (argu in ['+', '*', '/', '%', '**']):
        return
    entry.insert("end", argu)


def back(entry):
    l = len(entry.get())
    entry.delete(l - 1)


def clear(entry):
    entry.delete(0, "end")


def calculate(entry):
    date = entry.get()
    if not date:
        return
    else:
        for i in date:
            if i not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '+', '=', '*', '/', '%', '.']:
                t = 0
            else:
                t = 1
        if t == 0:
            error(2)
        else:
            clear(entry)
            result = str(eval(date))
            if len(result) > 20:
                entry.insert("end", "Value overflow")
            else:
                entry.insert("end", result)


def error(t):
    win0 = tk.Tk()
    win0.title("")
    if t == 1:
        l1 = ttk.Label(win0, text="无法运算")
        l1.grid(column=0, row=0, columnspan=2)
    elif t == 2:
        l1 = ttk.Label(win0, text="Illegal character")
        l1.grid(column=0, row=0, columnspan=2)
    b1 = ttk.Button(win0, text='关闭', command=lambda: win0.destroy())
    b1.grid(column=0, row=1)
    win0.mainloop()


def f1_get(entry):
    date = entry.get()
    if not date:
        return
    else:
        for i in date:
            if i not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']:
                t = 0
            else:
                t = 1
        if t == 0:
            error(1)
        else:
            entry.delete(0, "end")
            date = float(date)
            result = math.sqrt(date)
            entry.insert("end", result)


def f2down_get(entry):
    date = entry.get()
    if not date:
        return
    else:
        for i in date:
            if i not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']:
                t = 0
            else:
                t = 1
        if t == 0:
            error(1)
            return
        else:
            entry.delete(0, "end")
            date = float(date)
            result = math.trunc(date)
            entry.insert("end", result)


def f2up_get(entry):
    date = entry.get()
    if not date:
        return
    else:
        for i in date:
            if i not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']:
                t = 0
            else:
                t = 1
        if t == 0:
            error(1)
            return
        else:
            entry.delete(0, "end")
            date = float(date)
            result = math.ceil(date)
            entry.insert("end", result)


def f3_get(entry2, entry3, entry4):
    date1 = entry2.get()
    date2 = entry3.get()
    if (not date1) or (not date2):
        return
    else:
        for i in (date1 or date2):
            if i not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']:
                t = 0
            else:
                t = 1
        if t == 0:
            error(1)
        else:
            entry4.delete(0, "end")
            date1 = float(date1)
            date2 = float(date2)
            result = math.log(date1, date2)
            entry4.insert("end", result)


def f3_clear(entry2, entry3, entry4):
    entry2.delete(0, "end")
    entry3.delete(0, "end")
    entry4.delete(0, "end")


def f3():
    win2 = tk.Tk()
    win2.title("对数运算")
    l1 = ttk.Label(win2, text="对数运算")
    l1.grid(column=0, row=0, columnspan=3)
    l1 = ttk.Label(win2, text="请输入真数")
    l1.grid(column=0, row=1)
    l1 = ttk.Label(win2, text="请输入底数")
    l1.grid(column=0, row=2)
    l1 = ttk.Label(win2, text="结果为")
    l1.grid(column=0, row=3)
    entry2 = ttk.Entry(win2, width=20, justify="right", font=1)
    entry2.grid(row=1, column=1, columnspan=2, padx=20, pady=5)
    entry3 = ttk.Entry(win2, width=20, justify="right", font=1)
    entry3.grid(row=2, column=1, columnspan=2, padx=20, pady=5)
    entry4 = ttk.Entry(win2, width=20, justify="right", font=1)
    entry4.grid(row=3, column=1, columnspan=2, padx=20, pady=5)
    b1 = ttk.Button(win2, text='log运算', command=lambda: f3_get(entry2, entry3, entry4))
    b1.grid(column=2, row=4)
    b2 = ttk.Button(win2, text='clear', command=lambda: f3_clear(entry2, entry3, entry4))
    b2.grid(column=1, row=4)
    win2.mainloop()


def f4_get(entry5, entry6, entry7):
    date1 = entry5.get()
    date2 = entry6.get()
    if (not date1) or (not date2):
        return
    else:
        for i in (date1 or date2):
            if i not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']:
                t = 0
            else:
                t = 1
        if t == 0:
            error(1)
        else:
            entry7.delete(0, "end")
            date1 = int(date1)
            date2 = int(date2)
            result = math.gcd(date1, date2)
            entry7.insert("end", result)


def f4_clear(entry5, entry6, entry7):
    entry5.delete(0, "end")
    entry6.delete(0, "end")
    entry7.delete(0, "end")


def f4():
    win2 = tk.Tk()
    win2.title("最大公约数运算")
    l1 = ttk.Label(win2, text="最大公约数运算")
    l1.grid(column=0, row=0, columnspan=3)
    l1 = ttk.Label(win2, text="请输入第一个数")
    l1.grid(column=0, row=1)
    l1 = ttk.Label(win2, text="请输入第二个数")
    l1.grid(column=0, row=2)
    l1 = ttk.Label(win2, text="结果为")
    l1.grid(column=0, row=3)
    entry5 = ttk.Entry(win2, width=20, justify="right", font=1)
    entry5.grid(row=1, column=1, columnspan=2, padx=20, pady=5)
    entry6 = ttk.Entry(win2, width=20, justify="right", font=1)
    entry6.grid(row=2, column=1, columnspan=2, padx=20, pady=5)
    entry7 = ttk.Entry(win2, width=20, justify="right", font=1)
    entry7.grid(row=3, column=1, columnspan=2, padx=20, pady=5)
    b1 = ttk.Button(win2, text='运算', command=lambda: f4_get(entry5, entry6, entry7))
    b1.grid(column=2, row=4)
    b2 = ttk.Button(win2, text='clear', command=lambda: f4_clear(entry5, entry6, entry7))
    b2.grid(column=1, row=4)
    win2.mainloop()


def f5_get(entry8, s):
    date = entry8.get()
    if not date:
        return
    else:
        for i in date:
            if i not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']:
                t = 0
            else:
                t = 1
        if t == 0:
            error(1)
        else:
            entry8.delete(0, "end")
            date = float(date)
            if s == 2:
                result = math.degrees(date)
            if s == 3:
                result = math.radians(date)
            if s == 4:
                result = math.sin(math.pi * date)
            if s == 5:
                result = math.cos(math.pi * date)
            if s == 6:
                result = math.tan(math.pi * date)
            entry8.insert("end", result)


def f5():
    win2 = tk.Tk()
    win2.title("三角函数运算")
    l1 = ttk.Label(win2, text="三角函数运算")
    l1.grid(column=0, row=0, columnspan=3)
    entry8 = ttk.Entry(win2, width=20, justify="right", font=1)
    entry8.grid(row=1, column=0, columnspan=3, padx=20, pady=5)
    b1 = ttk.Button(win2, text='弧度转换角度', command=lambda: f5_get(entry8, 2))
    b1.grid(column=1, row=2)
    b2 = ttk.Button(win2, text='角度转换弧度', command=lambda: f5_get(entry8, 3))
    b2.grid(column=2, row=2)
    b3 = ttk.Button(win2, text='sin(π*n)', command=lambda: f5_get(entry8, 4))
    b3.grid(column=0, row=3)
    b4 = ttk.Button(win2, text='cos(π*n)', command=lambda: f5_get(entry8, 3))
    b4.grid(column=1, row=3)
    b5 = ttk.Button(win2, text='tan(π*n)', command=lambda: f5_get(entry8, 3))
    b5.grid(column=2, row=3)
    b6 = ttk.Button(win2, text='clear', command=lambda: entry8.delete(0, "end"))
    b6.grid(column=0, row=2)
    win2.mainloop()


win = tk.Tk()
win.title("计算器")
menubar = tk.Menu(win)
menubar.add_command(label='向下取整',command=lambda:f2down_get(entry))
menubar.add_command(label='开方',command=lambda: f1_get(entry))
menubar.add_command(label='对数函数',command=lambda: f3())
menubar.add_command(label='最大公约数',command=lambda: f4())
menubar.add_command(label='三角函数',command=lambda: f5())


win.config(menu=menubar)

entry = ttk.Entry(win, justify="right", font=1)
entry.grid(row=0, column=0, columnspan=6, padx=20, pady=5)
b0 = ttk.Button(win, text='0', command=lambda: get(entry, '0'))
b0.grid(column=1, row=4)
b1 = ttk.Button(win, text='1', command=lambda: get(entry, '1'))
b1.grid(column=0, row=3)
b2 = ttk.Button(win, text='2', command=lambda: get(entry, '2'))
b2.grid(column=1, row=3)
b3 = ttk.Button(win, text='3', command=lambda: get(entry, '3'))
b3.grid(column=2, row=3)
b4 = ttk.Button(win, text='4', command=lambda: get(entry, '4'))
b4.grid(column=0, row=2)
b5 = ttk.Button(win, text='5', command=lambda: get(entry, '5'))
b5.grid(column=1, row=2)
b6 = ttk.Button(win, text='6', command=lambda: get(entry, '6'))
b6.grid(column=2, row=2)
b7 = ttk.Button(win, text='7', command=lambda: get(entry, '7'))
b7.grid(column=0, row=1)
b8 = ttk.Button(win, text='8', command=lambda: get(entry, '8'))
b8.grid(column=1, row=1)
b9 = ttk.Button(win, text='9', command=lambda: get(entry, '9'))
b9.grid(column=2, row=1)
bb0 = ttk.Button(win, text='.', command=lambda: get(entry, '.'))
bb0.grid(column=2, row=4)
bb1 = ttk.Button(win, text='+', command=lambda: get(entry, '+'))
bb1.grid(column=3, row=1)
bb2 = ttk.Button(win, text='-', command=lambda: get(entry, '-'))
bb2.grid(column=3, row=2)
bb3 = ttk.Button(win, text='*', command=lambda: get(entry, '*'))
bb3.grid(column=3, row=3)
bb4 = ttk.Button(win, text='/', command=lambda: get(entry, '/'))
bb4.grid(column=3, row=4)
bb5 = ttk.Button(win, text='回退', command=lambda: back(entry))
bb5.grid(column=0, row=4)
bb6 = ttk.Button(win, text='x^n', command=lambda: get(entry, '**'))
bb6.grid(column=5, row=1)
bb7 = ttk.Button(win, text='mod', command=lambda: get(entry, '%'))
bb7.grid(column=5, row=2)
bb8 = ttk.Button(win, text='clear', command=lambda: clear(entry))
bb8.grid(column=5, row=3)
bb9 = ttk.Button(win, text='=', command=lambda: calculate(entry))
bb9.grid(column=5, row=4, )

win.mainloop()
  • 引入tkinter进行窗口化设计。在窗口化时简单的功能可以合并到表达式的计算中去。
  • 最终效果如图:



  • 计算实例

  • 结果为

  1. 一个计算器的编写就完成了
    代码链接https://gitee.com/DKY2019/lyx13579522789/blob/master/计算器GUI.py

4.实验中遇到的问题

  1. 计算三角函数时为弧度制,使用不方便

解决方法:在计算时引入math.pi进行处理

  1. 在使用eval()函数时能运行命令行,有安全风险

解决方法:在调用函数前先检查是否有非法字符

  1. 在tkinter中设置按钮时无法正常调用函数

解决方法:在要调用的函数前再用lambda:调用

5.感悟

  • 在编写代码之前要对自己希望实现的功能和效果有大致的设想,包括可以用什么库实现什么功能,大概的循环体结构,界面样式;
  • 如果要设计GUI界面的话,可以先找一张草稿纸,画出自己想要的菜单按钮,大致考虑好这些按钮的位置,和整体界面的大小,这样在代码实现的时候就会比较方便容易。
  • python库真的非常丰富非常强大,有句话说的就是不必重复造车轮,意思就是我们要学会baidu我们包含想要实现功能的库,总能在浩如烟海的库中找到需要的那一个。

参考资料

https://www.cnblogs.com/xiaoyh/p/9791670.html
https://blog.csdn.net/weixin_42795087/article/details/89931944
https://www.cnblogs.com/mxh1099/p/5386529.html

原文地址:https://www.cnblogs.com/DKYcaiji/p/14749226.html