0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

《Python程序设计》实验二报告

li5236 来源:博客园 作者:博客园 2022-03-30 15:16 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1.实验内容

(1)设计并完成一个完整的应用程序,完成加减乘除模等运算,功能多多益善。

(2)考核基本语法、判定语句、循环语句、逻辑运算等知识点。

2. 实验过程及结果

(1)设计思路

该实验目标是制作一个计算器,能够完成加减乘除、求余等运算,我选择参考手机系统自带的计算器进行实现。简单的运算能够使用运算符直接计算,开平方根等复杂运算通过Python的标准库math实现。另一方面,使用pyqt5实现计算器的UI界面,便于用户使用和规范用户输入。输入完成后,对字符串进行识别并完成相应的计算过程。在设计阶段设想能否在用户输入的同时处理算式,简化代码,但由于要给用户提供退格功能,无法实现这个设想。于是采用了大三在编译原理课程上学到的知识:使用符号优先表和双栈算法来解决此问题。

(2)算法逻辑

双栈算法,即“边存边看,边走边算”,设置符号栈和数字栈,符号栈中存储运算符,数字栈中存储数字。同时设置符号优先表,为所有可能出现的符号设置优先级。程序从左到右扫描算式,遇到数字则将其压进数字栈;遇到符号则比较该符号与符号栈栈顶元素的优先级,若当前符号的优先级高,则将其压栈,否则取数字栈栈顶元素,与符号一起完成计算,并将结果压入数字栈。迭代整个过程,直到算式被识别完毕。

(3)主要代码介绍

部分代码有参考。

报告中只贴出了部分代码,全部代码已上传码云:运算部分,用户界面部分(使用qt designer生成.ui文件,通过pyqt5库将其转换为.py文件)

计算函数:

完成数字、运算符弹栈后的计算操作,阶乘、对数、开平方根等复杂运算通过math库完成

import math

def calculate(operator, n1, n2=0):

“”“

:param n1: float

:param n2: float

:param operator: + - * / ^ % ! lg ln √

:return: float

”“”

if operator == “+”:

return n1 + n2

if operator == “-”:

return n1 - n2

if operator == “*”:

return n1 * n2

if operator == “/”:

return n1 / n2

if operator == ‘^’:

return n1 ** n2

if operator == ‘%’:

return n1 % n2

if operator == ‘!’:

return math.factorial(n1)

if operator == ‘lg’:

return math.log10(n1)

if operator == ‘ln’:

return math.log(n1)

if operator == ‘√’:

return math.sqrt(n1)

return 0

符号优先级判断函数:

根据符号优先表,对比判断当前符号与符号栈栈顶符号的优先级,对数运算与平方根运算是一元运算,因此比乘、除等二元运算优先级高。

def decision(last_op, new_op):

“”“

:param last_op: 运算符栈的最后一个运算符

:param new_op: 从算式列表取出的当前运算符

:return: 1 代表弹栈运算,0 代表弹运算符栈最后一个元素, -1 表示入栈

”“”

# 定义5种运算符级别

grade1 = [‘+’, ‘-’]

grade2 = [‘*’, ‘/’, ‘%’, ‘!’, ‘^’]

grade3 = [‘lg’, ‘ln’, ‘√’]

grade4 = [‘(’]

grade5 = [‘)’]

if last_op in grade1:

if new_op in grade2 or new_op in grade3 or new_op in grade4:

# 说明连续两个运算优先级不一样,需要入栈

return -1

else:

return 1

elif last_op in grade2:

if new_op in grade3 or new_op in grade4:

return -1

else:

return 1

elif last_op in grade3:

if new_op in grade4:

return -1

else:

return 1

elif last_op in grade4:

if new_op in grade5:

return 0 # ( 遇上 ) 需要弹出 (,丢掉 )

else:

return -1 # 只要栈顶元素为(,当前元素不是)都应入栈。

else:

return -1

过程函数:

实现了双栈算法的函数,主要思路如上文所述。与二元运算不同的是,对数运算、平方根运算等一元运算只需要数字栈栈顶的一个元素即可。另外由于乘方运算的特殊性,函数中代表乘方运算的“!”符号一旦出现,就与数字栈栈顶的元素一起完成运算,并将结果压入数字栈,即乘方运算是不进入符号栈的。

def final_calc(formula_list):

num_stack = [] # 数字栈

op_stack = [] # 运算符栈

for e in formula_list:

operator = is_operator(e)

if not operator:

# 压入数字栈

# 字符串转换为符点数

num_stack.append(float(e))

else:

# 如果是运算符

while True:

# 如果该运算符是“!”,则不进入符号栈,马上算出数字栈栈顶元素的乘方,并将结果压入数字栈

if e == ‘!’:

num1 = num_stack.pop()

num_stack.append(calculate(e, num1))

break

# 如果运算符栈等于0无条件入栈

if len(op_stack) == 0:

op_stack.append(e)

break

# decision 函数做决策

tag = decision(op_stack[-1], e)

if tag == -1:

# 如果是-1压入运算符栈进入下一次循环

op_stack.append(e)

break

elif tag == 0:

# 如果是0弹出运算符栈内最后一个(, 丢掉当前),进入下一次循环

op_stack.pop()

break

elif tag == 1:

# 如果是1弹出运算符栈内最后两个元素,弹出数字栈最后两位元素。

op = op_stack.pop()

if op == ‘lg’ or op == ‘ln’ or op == ‘√’:

num1 = num_stack.pop()

num_stack.append(calculate(op, num1))

else:

num2 = num_stack.pop()

num1 = num_stack.pop()

# 执行计算

# 计算之后压入数字栈

num_stack.append(calculate(op, num1, num2))

# 处理大循环结束后 数字栈和运算符栈中可能还有元素 的情况

while len(op_stack) != 0:

op = op_stack.pop()

if op == ‘lg’ or op == ‘ln’ or op == ‘√’:

num1 = num_stack.pop()

num_stack.append(calculate(op, num1))

else:

num2 = num_stack.pop()

num1 = num_stack.pop()

# 执行计算

# 计算之后压入数字栈

num_stack.append(calculate(op, num1, num2))

return num_stack, op_stack

用户界面

使用pyqt5库和qt designer,仿照手机计算器完成的用户界面。

class MyWindows(QtWidgets.QMainWindow, Ui_MainWindow):

def __init__(self, parent=None):

# 忽略pycharm检测失误导致的警告信息↓

# noinspection PyArgumentList

QtWidgets.QMainWindow.__init__(self, parent)

self.setupUi(self)

self.e = str(math.e)

self.pi = str(math.pi)

self.zero_button.clicked.connect(lambda: self.get_formula(‘0’))

self.one_button.clicked.connect(lambda: self.get_formula(‘1’))

self.two_button.clicked.connect(lambda: self.get_formula(‘2’))

# 共29个按键,隐藏部分相似代码,全部代码见上文中的码云链接

self.clear.clicked.connect(self.clean_screen)

self.back_space.clicked.connect(self.delete_char)

self.equa_button.clicked.connect(self.get_result)

self.formula = ‘’

def set_cursor(self):

# 设置输出框游标

self.showout.ensureCursorVisible()

cursor = self.showout.textCursor()

pos = len(self.showout.toPlainText())

cursor.setPosition(pos)

self.showout.setTextCursor(cursor)

def get_formula(self, param):

# 获取输入

if param == ‘lg’ or param == ‘ln’:

temp_param = param + ‘(’

elif param == ‘re’:

temp_param = ‘^(-1)’

else:

temp_param = param

self.formula += temp_param

self.showout.insertPlainText(temp_param)

self.set_cursor()

# print(self.formula)

def clean_screen(self):

# 清空输出框

self.formula = ‘’

self.showout.clear()

self.set_cursor()

def delete_char(self):

# 退格

self.showout.ensureCursorVisible()

cursor = self.showout.textCursor()

cursor.deletePreviousChar()

self.formula = self.formula[:-1]

def get_result(self):

# 运算

formula_list = formula_format(self.formula)

# print(formula_list)

result, _ = final_calc(formula_list)

# print(result[0])

show_result = ‘=’ + str(result[0])

self.showout.append(show_result)

self.formula = ‘’

self.showout.insertPlainText(‘\n’)

self.set_cursor()

if __name__ == ‘__main__’:

app = QtWidgets.QApplication(sys.argv)

main_window = MyWindows()

main_window.setFixedSize(main_window.width(), main_window.height())

main_window.show()

sys.exit(app.exec_())

在qt designer中设计的.ui文件如下图所示:

(4)程序结果

如下图所示,图片左边为我的程序结果,右边为手机计算器的运算结果。从两者对比来看,本程序的运算能力有所保障。

3. 实验过程中遇到的问题和解决过程

问题1:输出框不能自动滚动到最底部

问题1解决方案:在博客园找到了解决方案,虽然不完全贴合我的情况,但稍加改动后就实现了想要的效果。

问题2:不知道如何实现退格功能

问题2解决方案:在一位大佬的个人博客里找到了实现的方法,在文章大概中间的位置介绍了如何实现QTextEdit的两种删除操作。

问题3:在pyqt5启动的用户界面下,程序运算出错时进程会直接崩溃退出,且不会在cmd中trace back,给debug带来了很多麻烦。

问题3解决方案:不要直接运行,而是使用调试模式,这样出错能够看到trace back。这也提醒了我在调试程序阶段不要直接运行,使用调试模式更稳妥。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 程序设计
    +关注

    关注

    3

    文章

    263

    浏览量

    31561
  • python
    +关注

    关注

    57

    文章

    4858

    浏览量

    89599
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    LABVIEW 2023 Q1调用python后一直报错1671

    LABVIEW 2023Q1调用python后一直报错1671报错信息:PythonNode_AddTwoDoubles.vi中的打开Python会话Python returned
    发表于 11-12 09:51

    挖到宝了!人工智能综合实验箱,高校新工科的宝藏神器

    这款实验箱涵盖了9门课程,包括Python程序设计、机器学习、机器视觉、深度学习、深度视觉、数字图像处理、嵌入式系统及应用、语音识别与传感器、基于视觉的机器人应用。
    的头像 发表于 08-07 14:51 572次阅读
    挖到宝了!人工智能综合<b class='flag-5'>实验</b>箱,高校新工科的宝藏神器

    挖到宝了!人工智能综合实验箱,高校新工科的宝藏神器

    和深度至关重要。这款实验箱涵盖了9门课程,包括Python程序设计、机器学习、机器视觉、深度学习、深度视觉、数字图像处理、嵌入式系统及应用、语音识别与传感器、基于视觉的机器人应用。从基础的程序
    发表于 08-07 14:30

    挖到宝了!比邻星人工智能综合实验箱,高校新工科的宝藏神器!

    和深度至关重要。这款实验箱涵盖了9门课程,包括Python程序设计、机器学习、机器视觉、深度学习、深度视觉、数字图像处理、嵌入式系统及应用、语音识别与传感器、基于视觉的机器人应用。从基础的程序
    发表于 08-07 14:23

    IBM发布2025年第季度业绩报告

    今天,IBM (NYSE: IBM) 发布了 2025年第季度业绩报告
    的头像 发表于 07-29 13:55 796次阅读

    委托测试报告和型式检验报告什么区别

    委托测试报告和型式检验报告是两个不同的概念,它们在认证和合规过程中都有重要作用,但它们的内容、使用范围和法律效力有所不同。一、委托测试报告委托测试报告是由设备制造商或产品进口商委托第三
    的头像 发表于 07-03 11:43 1376次阅读
    委托测试<b class='flag-5'>报告</b>和型式检验<b class='flag-5'>报告</b>什么区别

    基于STM32 人群定位、调速智能风扇设计(程序、设计报告、视频演示)

    基于STM32 人群定位、调速智能风扇设计(程序、设计报告、视频演示),有需要的同学推荐下载!
    发表于 05-28 21:34

    程序设计与数据结构

    程序设计与数据结构》重点阐述了三大方向内容: 1. C语言学习中的痛点:针对当前工程师在C语言学习中的痛点,如指针函数与函数指针,如何灵活应用结构体等。从变量的三要素(变量的类型,变量的值和变量
    发表于 05-13 16:45

    零基础入门:如何在树莓派上编写和运行Python程序

    在这篇文章中,我将为你简要介绍Python程序是什么、Python程序可以用来做什么,以及如何在RaspberryPi上编写和运行一个简单的Pyth
    的头像 发表于 03-25 09:27 1538次阅读
    零基础入门:如何在树莓派上编写和运行<b class='flag-5'>Python</b><b class='flag-5'>程序</b>?

    是否可以使用OpenVINO™部署管理器在部署机器上运行Python应用程序

    使用 OpenVINO™部署管理器创建运行时软件包。 将运行时包转移到部署机器中。 无法确定是否可以在部署机器上运行 Python 应用程序,而无需安装OpenVINO™ Toolkit 和 Python
    发表于 03-05 08:16

    有没有什么方案能实现直接用matlab或python调用D4100_usb.dll?

    是32位程序而我的电脑是64位的。 由于实验中主要用matlab编程,使用C++程序很不方便,如果能直接用matlab或python调用D4100_usb.dll就会好很多。 因此,我
    发表于 02-27 06:59

    Python Connector for InterBase连接解决方案

    适用于 InterBase 的 Python 连接器 Python Connector for InterBase 是一种可靠的连接解决方案,用于从 Python 应用程序访问 Int
    的头像 发表于 01-22 14:34 716次阅读

    ID读卡器Python程序开发

    液显ID读卡器UDP协议开发Python程序。代码如下:   # pip install netifacesimport subprocessimport structimport
    的头像 发表于 01-10 16:05 771次阅读

    RK3568国产芯教学实验箱:指纹识别实战案例

    一、实验目的1、熟悉Qt程序的开发流程。2、掌握QtCreator的基础开发使用。3、通过编写Qt程序实现指纹识别的显示界面。实验原理Q
    的头像 发表于 01-08 19:05 1186次阅读
    RK3568国产芯教学<b class='flag-5'>实验</b>箱:指纹识别实战案例

    RK3568国产处理器实验平台:语音识别控制实验

    一、实验目的1、熟悉Qt程序的开发流程。2、掌握QtCreator的基础开发使用。3、通过编写Qt程序实现语音识别的显示界面。实验原理Q
    的头像 发表于 01-02 19:04 1715次阅读
    RK3568国产处理器<b class='flag-5'>实验</b>平台:语音识别控制<b class='flag-5'>实验</b>