20201113 2020-2021-2 《Python程序设计》实验报告
课程:《Python程序设计》
班级: 2011
姓名: 耿翔宇
学号:20201113
实验教师:王志强
实验日期:2021年4月26日
必修/选修: 公选课
1.实验内容
1.设计一个简单的计算器,内容包括:
- 简单的四则运算(可同时包含多个加减乘除运算,但不支持含括号的运算)
- 求模运算
- 求阶乘
- 指数运算
- 角度和弧度的转化
- 基本三角函数
2.练习条件、循环等基本语句以及函数、类等知识点。
2. 实验过程及结果
1.四则运算
先设计最简单的四则运算,最先想到的方法是直接输入两个数,再使用算术运算符进行求解,但这样的局限性太大,需要进行两次输入,且只能对两个数进行简单运算,每次运算还要人为选择是哪种运算。所以我打算在输入时直接输入运算式,再判断式子中有什么符号来确定运算类型,最后直接蒋结果输出。这样就需要提取运算符两边的数字,对这两个数字进行运算,可以使用split函数对输入的运算式进行切割,切割后将两个字符串转化为数字进行运算。这样一来函数比较复杂,创建class可以更加简洁明确。
要注意减法时第一个数可能是负数,此时需进行判断,若输入的字符串以 ’-‘ 开头,则从第二位开始截取一个新的字符串进行切割,切割完再加上负号。
class basic: ''' 基本四则运算(无法进行带括号的运算) ''' def __init__(self, expression): self.expression = expression def addition(self, expression): #加法 num = expression.split('+',1) return float(num[0]) + float(num[1]) def subtraction(self, expression): #减法 if expression.startswith('-') :#第一个数字是负数 expression = expression[1:] num = expression.split('-',1) num[0] = '-' + num[0] else : num = expression.split('-',1) return float(num[0]) - float(num[1]) def multiplication(self, expression): #乘法 num = expression.split('*',1) return float(num[0]) * float(num[1]) def devision(self, expression): #除法 num = expression.split('/',1) return float(num[0]) / float(num[1]) def calculation(self, expression): #判断运算式为何种运算 expression = expression.group() if '+' in expression: return self.addition(expression) if '-' in expression: return self.subtraction(expression) if '*' in expression: return self.multiplication(expression) if '/' in expression: return self.devision(expression)
这样一来计算器就显得更加专业了,但是却也只能进行两个数字之间的运算。如果要求多个数字之间的运算结果,就要对运算式进行多次切割,但是因为涉及到四种运算符,不太好操作,所以我决定尝试使用递归函数,对运算式进行迭代运算,这样就能解决多个数字的运算。但是由于四种运算有先后顺序,所以需要先对乘除法进行运算。这里可以使用正则表达式提取高运算级的操作,再从高到低一步步完成运算。
def sorting(self, expression): #按运算顺序计算 pattern_high = re.compile('(\d+\.?\d*(\*|\/)+\-?\d+\.?\d*)') #高运算级 pattern_low = re.compile('(\-?\d+\.?\d*(\+|\-)+\d+\.?\d*)') #低运算级 if re.search(pattern_high, expression): #递归 expression = re.sub(pattern_high, self.calculation, expression) return self.sorting(expression) elif re.search(pattern_low, expression): expression = re.sub(pattern_low, self.calculation, expression) return self.sorting(expression) else: expression return expression
expression = input('请输入运算式:') count = basic(expression) result = count.sorting(expression) print('结果为:', result)
这样就能较好的解决上述问题。但是如果运算式里有括号时,运算顺序被打乱,此时求解比较复杂,我暂时也还没想到比较好的解决方法,因此这个计算器只适用于不包含括号的四则运算。
求模运算与指数运算
因为算数运算符中有直接求余(模)和求幂的运算,所以设计这两种运算时比较简单,为了输入简洁,所以也像上述四则运算一样创建了一个求模的class,将输入的运算式分割后直接求模(幂)。
class mod_function(): ''' 求模运算 ''' def __init__(self,expression): self.expression = expression def calculation(self,expression): num = expression.split('%') return int(num[0]) % int(num[1]) class index_function(): ''' 指数运算 ''' def __init__(self,expression): self.expression = expression def calculation(self,expression): num = expression.split('^') return int(num[0]) ** int(num[1]) expression = input('请输入计算式如:x % y\n') mod = mod_function(expression) result = mod.calculation(expression) print('结果为:', result) expression = input('请输入计算式如:x ^ y\n') index = index_function(expression) result = index.calculation(expression) print('结果为:',result)
求阶乘
求阶乘只需输入一个数,所以不用再创建class和函数,直接涉及一个for循环即可完成。
z = int(input('请输入求阶乘的值:')) result = 1 for i in range(1,z + 1): result = result * i print('结果为:',result)
弧度/角度转换
弧度和角度的互相转换可以通过math函数库里的radians()和degrees()来完成,因为只有一个数字输入,所以可以直接调用函数来完成。
degree = float(input('输入角度:')) print('结果为:',math.radians(degree)) rad = float(input('输入弧度:')) print('结果为:',math.degrees(rad))
简单三角函数
简单三角函数(sin、cos、tan)可以在math函数库中找到,但因为输入时包含函数名,所以创建一个class,利用求模运算的方法也可以很快设计好。
要注意因为函数名(如sin)在计算式开头,所以用split切割后第一个字符串是空字符串,所以要对第二个字符串(索引为1)进行运算。另外因为sin等函数的输入为弧度制,但是用户输入一般为角度值,所以要先把输入的角度转化为弧度。
class degree_function(): ''' 求三角函数(输入为角度) ''' def __init__(self,expression): self.expression = expression def calculation(self,expression): #expression = expression.group() if 'sin' in expression: num = expression.split('sin') degree = float(num[1]) return math.sin(math.radians(degree)) elif 'cos' in expression: num = expression.split('cos') degree = float(num[1]) return math.cos(math.radians(degree)) elif 'tan' in expression: num = expression.split('tan') degree = float(num[1]) return math.tan(math.radians(degree)) expression = input('请输入计算式:') degree_1 = degree_function(expression) result = degree_1.calculation(expression) print('结果为:',result)
最后加上菜单,通过一个if-elif语句将所有的选项连在一起,大功告成!
代码全文如下:
3. 实验过程中遇到的问题和解决过程
- 问题1:在最初设计四则运算时无法进行多个数的复杂运算
问题1解决方案:一开始打算把运算式中的所有运算符号都切割开,再使用if语句一个个判断,最后得出结果,但是这样很难实现,所以不得不放弃。后查阅资料发现可以使用正则表达式,于是自己尝试写了两个正则表达式提取优先级,最后再迭代运算,就能较好的解决问题。唯一的遗憾是是对含括号的运算束手无策。
- 问题2:在使用递归函数迭代运算时系统提示出错,无法得出结果
问题2解决方案:在调试程序后发现,迭代后原本切割后形成的两个字符串还要再进行切割,因此要将运算后得到的结果转化为str型,才能继续进行迭代,而不能直接返回float或者int型的结果。
- 问题3:一开始进行四则运算时函数太多,显得关系很乱
问题3解决方案:创建一个class类,将四则运算有关的函数写进类的方法里,这样一来调用函数就更加简便,逻辑更加清晰,后续的其他运算也采用此方法。
其他(感悟、思考等)
python中基础的运算蕴藏着最基本的灵魂,熟悉从基础开始才能一步一步窥探到全貌。在使用 字符串相关函数对字符串进行切割、截取时,我体会到了python的简洁高效,一些看似不起眼的函数可以实现很强大的功能,这是我以前不敢现象的。在实验过程中我也遇到了不少困难,我买的教材上缺少正则表达式和字符串函数的部分内容,导致我在操作中走了不少弯路,最后通过上网查找才解决了一些问题。python是个巨大的宝藏,我现在认识到的还仅仅是冰山一角,以后还要不断练习、学习新的知识,温故知新,才能更好的掌握这个工具。
4.参考资料