目录
第4关:函数模块与循环 - 使用 Machin 公式计算圆周率
第1关:循环结构 - 数学中的累加运算
任务描述
本关任务通过圆周率计算的案例介绍 Python 循环相关知识,并使用 Python 循环结构编写代码完成数值累加计算。
相关知识
累加计算公式
在数学中,累加计算公式如下:
S=i=1∑Ni2
其中,S
表示累加求和的结果,N
表示累加计数的终止值,i
表示累加表达式的变量。
for
循环
为了让计算机能计算成千上万次的重复运算,就需要循环语句。Python 的循环有两种,一种是for...in
循环,依次把list
或tuple
中的每个元素迭代出来。示例如下:
names = ['Michael', 'Bob', 'T\fracy']
for name in names:
print(name)
其中,names
是一个字符串列表,执行这段代码,会依次打印names
的每一个元素:
Michael
Bob
T\fracy
所以for x in ...
循环就是把每个元素代入变量x
,然后执行缩进块的语句。再比如我们想计算 1 - 10 的整数之和,可以用一个sum
变量做累加:
sum = 0
for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
sum = sum + x
print(sum)
如果要计算 1 - 100 的整数之和,从 1 写到 100 有点困难,幸好 Python 提供一个range()
函数,可以生成一个整数序列。
range(101)
就可以生成 0 - 100 的整数序列(range
函数的具体调用可参考中文文档和官方英文文档),所以可以通过如下程序计算 1 - 100 的整数之和:
sum = 0
for x in range(101):
sum = sum + x
print(sum)
while
循环
Python 中的第二种循环是while
循环:只要条件满足,就不断循环,条件不满足时退出循环。比如我们要计算 100 以内所有奇数之和,可以用while
循环实现:
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)
在循环中,break
语句可以在循环过程中直接退出循环,而continue
语句可以提前结束本轮循环,并直接开始下一轮循环,这两个语句通常都必须配合if
判断语句使用。
编程要求
根据累加计算公式
S=i=1∑Ni2
在右侧编辑器补充代码,计算出 1 到 N 的整数平方之和,计算并打印最终结果。
测试说明
本实训测试样例如下:
测试输入:100
预期输出:338350
开始你的任务吧,祝你成功!
# 本程序计算1-N整数平方的累加和
N = int(input())
# 请在此添加实现代码 #
# ********** Begin *********#
sum = 0
for i in range(N + 1):
sum = sum + i ** 2
print(sum)
# ********** End **********#
第2关:列表与循环 - 验证是否为三位数
任务描述
本关任务要求结合 Python 列表以及循环结构编写代码,验证一个给定的整数是否为三位数。
相关知识
Python 序列
序列是 Python 中最基本的数据结构。相比于单一变量只能存储一个对象(数字或者字符串),序列可以用于存储多个对象。Python 有 6 种内置的序列类型,但最常见的是列表(list
)和元组(tuple
)。
列表list
list
是一种有序的集合,可以随时添加和删除其中的元素。列表的数据项不需要具有相同的类型。创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可,如下所示:
list1 = ['physics', 'chemistry', 1997, 2000]
list2 = [1, 2, 3, 4, 5 ]
在list
中用索引来访问list
中每一个位置的元素。注意索引是从 0 开始的,当索引超出了范围时,Python 会报一个IndexError
错误。所以,要确保索引不要越界,记得最后一个元素的索引是len(list) - 1
。
例如,要获取上面示例代码中的list1
中的第 2 个元素,则可以通过下面的代码来获得:
>>> list1[1] #索引是从 0 开始的,所以第二个元素对应的索引是 1 而不是 2。
chemistry
列表list
包含以下方法:
方法 | 功能 |
---|---|
list.append(obj) | 在列表末尾添加新的对象 |
list.count(obj) | 统计某个元素在列表中出现的次数 |
list.extend(seq) | 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) |
list.index(obj) | 从列表中找出某个值第一个匹配项的索引位置 |
list.insert(index, obj) | 将对象插入列表 |
list.pop([index=-1]) | 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值 |
list.remove(obj) | 移除列表中某个值的第一个匹配项 |
list.reverse() | 反向列表中元素 |
元组tuple
Python 的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可,如下所示:
tup1 = ('physics', 'chemistry', 1997, 2000)
tup2 = (1, 2, 3, 4, 5 )
tup3 = (1,)
元组中只包含一个元素时,需要在元素后面添加逗号,以免被误解成数学计算意义上的括号。
元组中的元素不可变,所以它没有append()
,insert()
这样的方法。另外,元组中的元素值也是不允许删除的,但我们可以使用del
语句来删除整个元组。比如,del tup1
。
其他获取元素的方法和list
是一样的,你可以正常地使用tup1[0]
,tup1[-1]
,但不能赋值成另外的元素。元组这种不可变的特性能够使得代码更安全。
编程要求
请编写代码验证输入的列表N_list
中的整数是否为三位数,并求这些三位数的百位数值,并用列表存储,最终直接输出列表。
测试说明
本实训的测试样例如下:
测试输入:100,200,300,400,500
预期输出:[1, 2, 3, 4, 5]
开始你的任务吧,祝你成功!
#请验证输入的列表N_list中的整数是否为三位数,并返回三位数整数的百位数值
N_list = [int(i) for i in input().split(',')]
# 请在此添加实现代码 #
# ********** Begin *********#
my_list=[]
for i in N_list:
if i > 99 and i < 1000:
x = i // 100
my_list.append(x)
print(my_list)
# ********** End **********#
第3关:嵌套循环 - 使用莱布尼茨公式计算圆周率
任务描述
本关任务是学习和掌握嵌套循环的相关知识,并使用 Python 嵌套循环结构编写代码,实现使用莱布尼茨公式计算圆周率。相关教学视频可查看本实训第一关《数学中的累加计算》的视频内容。
相关知识
使用莱布尼茨公式计算圆周率
大家是否还记得读书时用谐音记忆法背过的圆周率π,“山巅一寺一壶酒(3.14159),尔乐苦煞吾(26535),把酒吃(897),酒杀尔(932),杀不死(384),乐尔乐(626)”。圆周率π是精确计算圆周长、圆面积、球体积等几何形状的关键值。溯古追今,圆周率有着很长的计算历史。德国数学家莱布尼茨(Leibniz)于 1674 年曾提出 Gregory-Leibniz 公式来计算π:
4π=1−31+51−71+...
其中,每一项的分母都为奇数,项数累积的越多,π的计算结果会收敛的更加准确。
pi = 4*(1-1/3+1/5-1/7+1/9)
当我们算到 1/9 时,π值约为 3.339682... ;
pi = 4*(1-1/3+1/5-1/7+1/9-1/11+1/13-1/15+1/17-1/19+ 1/21-1/23+1/25-1/27+1/29-1/31+1/33-1/35+1/37-1/39+ 1/41-1/43+1/45-1/47+1/49-1/51+1/53-1/55+1/57-1/59)
当我们算到 1/59 时,π值约为 3.108268... 。
Python 循环嵌套
Python 语言允许在一个循环体里面嵌入另一个循环,针对for
循环和while
循环的语法如下所示:
for
循环嵌套语法:
for i in s1:
for j in s2:
# do something
# do something else
上述代码示例是for
循环嵌套for
循环。首先执行外层循环,然后执行内层循环。
整个代码执行过程中,外层循环每执行一次,嵌套的内层循环全部执行一遍。假设外层循环需要执行 x 次,内层循环需要执行 y 次,则整个代码需要执行 x*y 次。
while
循环嵌套语法:
while expression1:
while expression2:
# do something
# do something else
while
嵌套循环同for
嵌套循环类似,首先执行外层循环,然后执行内层循环。整个代码执行过程中,外层循环每执行一次,嵌套的内层循环全部执行一遍。假设外层循环需要执行 x 次,内层循环需要执行 y 次,则整个代码需要执行 x*y 次。
此外,还可以在循环体内嵌入其他的循环体,比如在while
循环中可以嵌入for
循环,反之也可以在for
循环中嵌入while
循环。
编程要求
观察莱布尼茨公式,我们想要更加准确的计算出π值,则需要累积更多的项数,计算公式会越来越长。为了避免重复的计算操作,请你仔细观察该公式是否存在计算规律,并设计出循环结构来简化冗长的代码。
本关卡给出了一个列表N_list
,其中存储的是计算π最后一项的分母值(比如算到1/59时,存储的值为59)。
请编写程序,返回算到N_list
中每一项时的π值,π值需保留八位小数(字符串形式),并用列表存储,最终输出列表结果。
测试说明
本实训测试样例如下:
测试输入:1,11,111,1111,11111
预期输出:['4.00000000', '2.97604618', '3.12373693', '3.13979409', '3.14141267']
开始你的任务吧,祝你成功!
# 本程序要求返回算到N_list列表中每一项时的圆周率值,并用列表进行存储,最终输出列表结果
N_list = [int(i) for i in input().split(',')]
# 请在此添加实现代码 #
# ********** Begin *********#
my_list = []
for i in N_list:
sum = 0
for x in range(0,int((i+1)/2)):
sum = sum + (1 / (1 + 2 * x)) * (-1) ** x
result = sum * 4
my_list.append(result)
print(['{:.8f}'.format(i) for i in my_list])
# ********** End **********#
第4关函数模块与循环 - 使用 Machin 公式计算圆周率
任务描述
本关任务是结合 Python 函数和循环结构编写相应代码,完成 Machin 公式以更快速的计算出圆周率。
相关知识
Machin 公式更快计算圆周率
在上一关卡中,我们使用莱布尼茨公式来计算圆周率π,我们发现该方法的收敛速度非常慢,即使算到分母 999 ,也才精确到小数点后 1 位(对应的π值为 3.13959265... ),如下图所示。
因此,人们开始利用无穷级数或无穷连乘积求π。1706 年英国数学家梅钦(John Machin)提出 Machin 公式,计算得到的π值突破 100 位小数大关,该公式如下:
4π=4arctg51−arctg2391
arctg
函数可由泰勒级数(用无限项连加式 —— 级数来表示一个函数)算出,公式如下:
arctg(x)=x−3x3+5x5−7x7+...+(−1)n−12n−1x2n−1
泰勒级数展开的项数越多,即arctg
函数中的 n 值越大,函数值就会越精确。当项数等于 5 时,计算得到的圆周率等于 3.14159268240439937259 ,相当于我们的老祖宗祖冲之的计算结果,收敛速度大大加快。
Python 函数
函数是可重复使用的、用来实现单一或相关联功能的代码段,函数能提高应用的模块性和代码的重复利用率。 Python 提供了许多内建函数,比如print()
等等,用户也可以自己创建函数,即自定义函数。
函数定义
在 Python 中,定义函数需满足如下规则:
-
函数代码块以
def
关键词开头,后接函数标识符名称和圆括号 ( ) ; -
任何传入参数和自变量必须放在圆括号中间;
-
函数内容以冒号 : 起始,并且在缩进块中编写函数体;
-
return
语句用于结束函数,可选择性地返回一个值给调用方;不带表达式的return
相当于返回None
。
函数定义的语法结构如下所示:
def function_name(parameters):
function_body
return [expression]
例如,求绝对值的my_abs
函数示例如下:
def my_abs(x):
if x >= 0:
return x
else:
return -x
在上述示例代码中,定义了一个名为my_abs
的函数,参数x
表示要求绝对值的数。在函数体中,通过if...else...
分析判断参数x
的值,大于等于 0 则直接返回原值,否则返回该值的负值即可。
函数调用
在 Python 中,要调用一个函数需要知道函数的名称和参数,比如求绝对值的函数my_abs()
,只有一个参数。
比如:
print(my_abs(-5)) #输出结果为 5。
注意
- 如果传入的参数数量不对,会报
TypeError
的错误,并且 Python 会明确地告诉你:my_abs()
有且仅有1个参数; - 如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报
TypeError
的错误,并且给出错误信息:str
是错误的参数类型。
参数传递
Python 的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。
以power
函数为例,它主要用于计算幂次方。由于经常计算x2,所以把第二个参数n
的默认值设定为2
。
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
当调用power(5)
时,相当于调用power(5, 2)
;而对于n > 2
的其他情况,就必须明确地传入n
,比如power(5, 3)
。
从上面的例子可以看出,默认参数可以简化函数的调用。设置默认参数时,要注意必选参数在前,默认参数在后,否则 Python 的解释器会报错。
Python 长整数
由于计算机只能存储整数,所以实数都是约数,浮点运算就会出现误差, Python 可以支持长整数,从而提高计算的精度。
编程要求
为了使用Machin
方法更快的计算出π值,请在右侧代码框中编写程序实现arctg
函数,根据输入的x
和迭代项数N
返回相应的arctg
值。
测试说明
本实训的测试样例如下:
测试输入:0.1
预期输出:0.09966865249206348365
平台会使用下列代码调用你编写的函数:
from machin import arctg
print('%.20f' % arctg(float(input())))
开始你的任务吧,祝你成功!
# 请用函数实现Machin公式计算,包含隐含参数N
def arctg(x, N=5): # 迭代项数N的缺省值是5,即如果调用时不给值就用5
# 请在此添加实现代码 #
# ********** Begin *********#
result = 0
for i in range(0,N):
result = result + ((x ** (2 * i + 1)) / (2 * i + 1)) * (-1) ** i
return result
# ********** End **********#
第5关:函数与循环 - 自然对数的计算
任务描述
自然对数是以常数 e 为底的对数,在物理、生物等科学中具有非常重要的应用。本关任务要求利用 Python 编程实现自然对数函数。
相关知识
自然对数与麦克劳林级数
泰勒级数在近似计算中有重要作用,在上一关卡中也有提到用泰勒级数对 Machin 公式中的arctg
函数做近似计算。通过函数在自变量零点的导数求得的泰勒级数又叫做迈克劳林级数。
自然对数的麦克劳林级数的公式如下所示:
ln(x+1)=n=1∑∞n−1(n+1)xn∀x∈(−1,1]
公式展开如下所示,迭代项数越多,近似计算的值越精确:
ln(x+1)≈x−2x2+3x3−...+n−1(n+1)xn∀x∈(−1,1]
Python 函数返回值
Python 函数可以返回多个值,比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的坐标。其函数定义如下:
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
命令行调用运行结果如下:
>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print(x, y)
151.96152422706632 70.0
该函数返回值是一个元组tuple
。在语法上,返回一个tuple
可以省略括号,而多个变量可以同时接收一个tuple
,按位置赋给对应的值。所以,Python 的函数返回多值其实就是返回一个tuple
,但写起来更方便。
编程要求
请在右侧代码框中编写程序实现ln
函数,根据输入的x
和迭代项数N
(默认为 50 )计算对数值,并分析真实误差(相对于 math 库自然对数函数的计算结果)。
ln
函数将返回两个值:计算结果与误差的绝对值。
提示:
-
在 math 库中自然对数的函数名是
log
-
计算真实误差时需调用绝对值函数
fabs
测试说明
本实训的测试样例如下: 测试输入:2
预期输出:ln(2.00)=0.68324716 error=0.00990002
开始你的任务吧,祝你成功!
# 请实现ln函数
from math import *
def ln(x, N=50):
'''
:param x: 输入值
:param N: 迭代项数
:return: 对数值,误差的绝对值
'''
# 请在此添加实现代码 #
# ********** Begin *********#
result = 0
for i in range(1, N + 1):
result += (pow(x - 1,i) / i) * pow(-1, i + 1)
error = fabs(result - log(x))
return result,error
# ********** End **********#