这里写目录标题
- 【本章导读】
- 真值测试
- 比较运算
- 成员运算
- for循环
- while循环
- 项目实训1
- 项目实训2
- 项目实训3
- 项目实训4:
- 项目实训5:
- 项目实训6:
- 项目实训7:
- 项目实训8
- 项目实训9:
- 项目实训10:
- 项目实训11:
- 项目实训12:
- 项目实训13:
- 项目实训14:
- 项目实训15:
- 项目实训16:
- 项目实训17:
- 项目实训18:
- 项目实训19:
- 项目实训20:
【本章导读】
进行程序设计时,复杂问题的求解通常需要通过流程进行控制。程序的流程控制可归纳为三种:顺序结构、分支(选择)结构和循环结构。每一个结构化的程序都可以由这三种结构组合或嵌套而成。这种程序设计方法,使程序具有良好的可读性和可维护性。
本章在讲解常用运算的基础上,应用一系列数学问题的求解案例,详细介绍了Python中利用for
关键字对range()函数产生的整数序列进行确定次数循环的方法和具体应用,介绍了利用while关键字实现循环次数不确定问题的求解方法。
介绍了用if…elif…else语句实现分支结构程序设计。简单介绍了利用pass、continue和break语句实现流程跳转的方法。
简单介绍了异常处理的概念和利用异常处理提高程序健壮性和容错性的程序设计方法。
【本章要点】
●常用运算及运算优先级
数值运算: +、-、*、/、//、%、**
真值测试:None,False, 0, 0.0, 0j, Decimal(0), Fraction(0, 1),'', (), [], {}, set(), range(0)
布尔运算:x or y, x and y, not x
比较运算:>、 >=、 <、 <=、 ==、 !=、 is、 is not
成员运算:x in s 、x not in s
●for…in range()循环结构
for 循环变量 in 可遍历对象:重复执行的语句块
[else]:循环正常结束后需执行的语句for i in range(5): # 遍历rangeprint(i)
else:print('循环正常结束')for c in string: # 遍历字符串print(c)for item in list: # 遍历列表、元组、字典、集合等print(item)for line in file: # 遍历文件对象print(line)
●while循环结构的流程控制
while 条件表达式:重复执行的语句块
[else]: # 只有当循环正常结束时,else子句中的语句才能被执行循环正常结束后需执行的语句
●流程跳转语句的功能与应用
break 跳过当前循环中未执行的次数,提前结束当前层次循环
continue 跳过本次循环中剩余语句的执行,提前进入下一次循环
pass 跳过执行或占位
●分支语句
if 条件表达式1: # if 必须有且只能有一个语句块1
[elif 条件表达式2: # 有0个或多个语句块2]
[elif 条件表达式3:语句块3]
[……]
[else: # 0个或1个语句块n]
●异常处理的概念与应用
except <异常名称1>:<语句块2> # 如果在try部份引发了异常名称1时执行的语句块
[except <异常名称2>:<语句块3>] # 如果在try部份引发了异常名称2时执行的语句块
[else:<语句块4>] # 没有异常发生时执行的语句块
[finally:<语句块5>] # 无论有没有异常都会执行的语句块
思维导图:
真值测试
对象出现在if或while语句中的条件表达式中, 或是作为布尔运算的操作数时,对象值表现为 True或False
值为False的内置对象: 被定义为假值的常量 任何数值类型的数字零 空的序列和多项集
会被视为假值的内置对象包括:
假值常量: None和False
print(bool(False)) # False
print(bool(None)) # False
会被视为假值的内置对象包括: 任何数值类型的数字零:
0, 0.0, 0j, Decimal(0), Fraction(0, 1)
print(bool(0.0)) # False
print(bool(0j)) # False
print(bool(0)) # False
会被视为假值的内置对象包括: 空的序列和多项集,len()测试长度为0: 空字符串’', 空元组(), 空列表[], 空字典{},
空集合set(), range(0)
print(bool('')) # 空字符串,False
print(bool([])) # 空列表,False
print(bool(())) # 空元组,False
print(bool({})) # 空字典,False
print(bool(set())) # 空集合,False
print(bool(range(0))) # 空range,False
除上述对象外,所有其他对象的真值测试结果都为True
print(bool(0.00001)) # 非0浮点数
print(bool([1])) # 非空列表
print(bool((1,))) # 非空元组
print(bool('me')) # 非空字符串
print(bool({1, 2, 3})) # 非空集合
print(bool(range(5))) # 非空range
print(bool({'tom': 99, 'jerry': 86})) # 非空字典
比较运算
用于比较两个值,确定它们之间的关系
结果为逻辑值,即True 或False
8 种比较运算:
2 种一致性比较(==、!=)
4 种次序比较(<、>、<=、>=)
2 种标识号比较(is 和is not)
比较运算符可以连续使用
例如:x < y <= z90 <= score <= 100
等价于 x < y andy <= zscore >= 90 and score <= 100
数值类型会根据数字大小和正负进行比较
print(100 > 99) # True
print(3.14> 3.141) # False
print(1.0==1) # True,值相等的不同对象
整数和浮点数可以跨类型比较
print(1e18 == 1e18 + 10) # True
大浮点数比较精度影响结果
字符串比较根据其字符的Unicode 码数字值大小
按字典顺序进行
print('ji lin' > 'ji an') # True
print([ord(y) for y in 'ji lin’])
print([ord(x) for x in 'ji an'])
ord()获取字符Unicode 码数字值
[106, 105, 32, 108, 105, 110]
[106, 105, 32, 97, 110]
元组、列表和range等序列只可进行类型内部的比较
比较方法是依次比较元素的值
print([1, 2, 3, 4] > [1, 2, 3])# True
print((1, 2, 3, 4) > (1, 2, 3)) # True
print(range(5) == range(0,5)) # True
print([1, 2, 3, 4] > [3, 2, 3]) # False
print((3, 2, 3) > (1, 2, 3)) # True
None和任何其他的数据类型的一致性比较永远返回False
// An highlighted block
var foo = 'bar';print(range(0) == None)#RangeFalse
print([] == None)# 空列表,False
print('' == None)# 空字串符,False
print(0 == None)# 整数0,False
运算符is 和is not 用于检测对象的标识号是否相同
仅当id(x) == id(y)时,x is y 结果为True
print(id(5) == id(5.0)) # False
print(id(5),id(5.0)) # 21975364018402197543023344
print(5 is 5.0) # False
print(5 == 5.0) # True,值相等
成员运算
运算符in和not in 用于成员检测 如果x 是s 的成员则x ins 值为True,否则为False x not in s 返回x
ins 取反后的值 如果x 不是s 的成员则x not ins 值为True,否则为 False运算符in和not in 用于成员检测 对于字符串和字节串类型来说 当且仅当x 是y 的子串时,x iny 为True
print('admin' in 'administrator') # True
print('ada' in 'administrator') # False
print('' in 'admin') # False,空格字符串
运算符in和not in 用于成员检测 空字符串总是被视为任何其他字符串的 子串,因此’’ in 'admin’将返回True
print('' in 'admin') # True,空字符串
print('' in 'admin') # False,空格字符串
运算符in和not in 用于成员检测 所有内置序列、集合类型、字典都支持成员运算 测试元素x 是否为对象s 的一个成员(元素)
print(10 in range(1, 20)) # True
print('me' in {'you', 'me', 'he'}) # True
print('she' in {'you', 'me', 'he'}) # False
print(2 in [1, 2, 3, 4, 5]) # True
print(6 in [1, 2, 3, 4, 5]) # False
print([1, 2] in [[1, 1], [1, 2], [1, 3]]) # True
运算符in和not in 用于成员检测 所有内置序列、集合类型、字典都支持成员运算 测试元素x 是否为对象s 的一个成员(元素
)
print([1, 2] in [1, 2, 3, 4, 5]) # False
[1, 2] 1,2,3,4,5
print(range(5) in range(10)) # False
range(5) 0,1,2,3,4,5,6,7,8,9
运算符in和not in 用于成员检测 对于字典来说成员运算检测对象是否在字典的键中存在
print('me' in {'you': 100, 'me': 1000, 'he': 50})
print(100 in {'you': 100, 'me': 1000, 'he': 50})
for循环
for 循环 遍历循环 依据可遍历对象中的子项,按顺序进行迭代 重复次数确定时使用
for 循环变量in 可遍历对象:
重复执行的语句块
[else]:
循环正常结束后需执行的语句
for i in range(n): Range语句块
for c in string: 字符串语句块
for item in list: 列表(元组、集合、字典)语句块
for line in file: 文件对象语句块
while循环
依据判断条件表达式的结果决定是否执行循环
重复次数不确定时使用
while判断条件:
重复执行的语句块 [else]:
循环正常结束后需执行的语句continue break 应用于while或for循环语句中 置于条件判定语句块中 当满足某条件时触发该语句的执行 continue
应用于while或for循环语句中 跳过本次循环中剩余语句的执行 提前进入下一次循环
for i in range(40):if i % 3 == 0 or i % 10 == 3 or i // 10 == 3:continue # 跳过本次循环else语句
else:print(i, end=' ')
break
应用于while或for循环语句中
跳过当前循环中未执行的次数,提前结束当前层次循环
break应用:输出最大因子
num = int(input()) # 输入一个整数,例如:100
for i in range(num -1, 0, -1): # 遍历小于num且大于1的整数if num % i == 0: # 若i为num的因数print(i) # 输入100时,输出50break # 中止循环
break只能提前结束当前循环
当循环层数多于一层时,可以用一个标记变量
根据标记变量的值决定是否继续退出外层循环
break应用:百钱百鸡
公鸡5元一只,母鸡3元一只,小鸡3只一元。
用户输入想买的鸡的数量和付出的钱数,
计算公鸡、母鸡和小鸡的数量。
如果有解,输出公鸡最少,小鸡最多的一组;
如果无解则输出“无解”
def hundred_chickens(num, money):for cock in range(1, num): # 从小到大遍历公鸡数量for hen in range(1, num): # 从小到大遍历母鸡数量chicken = num -cock -hen # 小鸡数量计算得到if chicken % 3 == 0 and chicken > 0 and 5 * cock + 3 * hen + chicken // 3 == money:return cock,hen,chicken # 输出找到的第一组解else: # 两层循环都正常结束时,表明未找到解return '无解'if __name__ == "__main__":number,amount_of_money = map(int, (input().split())) # 切分空格分隔的输入转整型print(*hundred_chickens(number, amount_of_money))
项目实训1
兔子繁殖问题
描述
古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,用户输入一个月份数,计算并在一行内输出该月的兔子总对数。
输入
一个不小于2的正整数
输出
输出该月的兔子的对数
运行代码:
n = int(input('请输入一个月份数:'))
a, b = 1, 1
for i in range(n):print(a, end=' ')a, b = b, a+b
运行结果:
项目实训2
输出九九乘法表:
描述
输出乘法表,如下所示:
1*1= 1
21= 2 22= 4
31= 3 32= 6 3*3= 9
41= 4 42= 8 43=12 44=16
51= 5 52=10 53=15 54=20 5*5=25
61= 6 62=12 63=18 64=24 65=30 66=36
71= 7 72=14 73=21 74=28 75=35 76=42 7*7=49
81= 8 82=16 83=24 84=32 85=40 86=48 87=56 88=64
91= 9 92=18 93=27 94=36 95=45 96=54 97=63 98=72 9*9=81
运行代码:
for i in range(1, 10):for j in range(1, i + 1): # 每行输出10次print('{}*{}={}'.format(i, j, i*j), end=' ')print() # 内层循环结束时换到下一行
运行结果:
项目实训3
百钱买百鸡
描述
我国古代数学家张丘建在《算经》一书中提出的数学问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,如果要求鸡翁、鸡母、鸡雏都不为零,问鸡翁、鸡母、鸡雏各几何?
输入格式
该题目没有输入
输出格式
每行输出一组结果,按鸡翁数、鸡母数、鸡雏数的顺序输出,数字之间用空格分隔;
如果有多组解时,按鸡翁数量由少到多输出;
运行代码:
for cock in range(1,100):for hen in range(1,100):for chicken in range(3,100,3):if cock+hen+chicken==100 and 5*cock + 3*hen + chicken//3==100:print(cock,hen,chicken)
运行结果:
项目实训4:
计算圆周率——无穷级数法
描述
π是个超越数,圆周率的超越性否定了化圆为方这种尺规作图精确求解问题的可能性。有趣的是,π可以用无穷级数表示:
左边的展式是一个无穷级数,被称为莱布尼茨级数(Leibniz),这个级数收敛到π/4,它通常也被称为格雷戈里-莱布尼茨级数,用以纪念莱布尼茨同时代的天文学家兼数学家詹姆斯·格雷戈里。
编程用这个公式计算π值,输入一个小数作为阈值,当最后一项的绝对值小于给定阈值时停止计算并输出得到的π值。
输入格式:
一个正浮点数threshold,限定级数法求解pi值时,迭代累加只加绝对值大于threshold的项。
输出格式:
输出为一个浮点数,是程序使用级数法求解的pi值。
运行代码:
pi = 0
sign = 1
i=1
while 1/i>= 1e-7:pi=pi+sign*1/ii=i+2sign=-sign
print(pi*4)
运行结果:
项目实训5:
百分制成绩转换五分制F
描述
编写一个学生成绩转换程序,用户输入百分制的学生成绩,成绩大于等于 90 且小于等于 100 的输出为“A”,成绩大于或等于 80 且小于 90 的输出为“B”,成绩大于或等于 70 且小于 80 的输出为“C”,成绩大于或等于 60 且小于 70 的输出为“D”,成绩小于 60 且大于等于 0 的输出为“E”,如果输出的成绩大于 100 或小于 0 或输入中包含非数字字符,输出’data error!'。
输入格式
输入一个浮点数,代表百分制成绩。
输出格式
A、B、C、D、E中的一个字母,表示五分制的成绩等级;或输出’data error!’
运行代码:
gra = float(input('请输入成绩:'))
if 90 <= gra <= 100:print('A')
if 80 <= gra < 90:print('B')
if 70 <= gra < 80:print('C')
if 60 <= gra < 70:print('D')
if 0 <= gra < 60:print('E')
if gra > 100 or gra < 0:print('data error!')
运行结果:
项目实训6:
与3有关的数
描述
一个正整数,如果它能被3整除,或者它的十进制表示法中某一位的数字为3,则称其为与3相关的数,否则就是与3无关的数。
查找并输出40以内与3有关数。
输入格式
无
输出格式
所有与3有关的数
运行代码:
# 查找并输出40以内与3有关数。
for i in range(1, 40):if i % 3 == 0 or i % 10 == 3 or i // 10 == 3:print(i, end=" ")
# 输入一个数,输出不大于这个数所有与3有关的数
num = int(input('请输入一个整数:'))
for i in range(num + 1):if i % 3 == 0 or i % 10 == 3 or i // 10 == 3:print(i, end=" ")
运行结果:
项目实训7:
最大因数
描述
输入一个大于1的整数,输出其自身以外的最大因数
输入格式
输入一个大于1的整数
输出格式
最大因数
运行代码:
num = int(input('请输入一个大于1的整数:'))
ls = []
for i in range(1, num):if num % i == 0:ls.append(i)
print(ls[-1])
运行结果:
项目实训8
判断素数
描述
依次判定10以内的数是否是素数,是素数时输出该数是素数,否则输出其因式分解
输入格式
无
输出格式
示例:
3是素数
4 = 2 * 2,不是素数
运行代码:
for num in range(2, 11):for i in range(2, num):if num % i == 0:print(f'{num}={num}*{num // i},{num}不是素数!', end='')breakelse:print(f'{num}是素数!', end='')
运行结果:
项目实训9:
百钱买百鸡
描述
我国古代数学家张丘建在《算经》一书中提出的数学问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,如果要求鸡翁、鸡母、鸡雏都不为零,问鸡翁、鸡母、鸡雏各几何。
现在的问题是:用户输入鸡的数量和钱数,鸡翁、鸡母、鸡雏各为多少?如果有解,输出全部解,并按鸡翁数量由少到多的顺序输出;如果无解则输出“无解”。
输入格式
用户在同一行内输入用空格分隔的两个正整数,分别表示鸡的数量和钱数
输出格式
每行输出一组结果,按鸡翁数、鸡母数、鸡雏数的顺序输出;
有多组解时,按鸡翁数量由少到多输出;
如果无解则输出“无解”。
运行代码:
num, m = map(int, input().split())
flag = 0
for cock in range(1, num):for hen in range(1, num):for chicken in range(3, num, 3):if cock + hen + chicken == num and 5 * cock + 3 * hen + chicken // 3 == m:print(cock, hen, chicken)flag = 1breakif flag == 1:breakif flag == 1:break
if flag == 0:print('无解')
运行结果:
项目实训10:
最小公倍数
描述
输入一个正整数n,判断在1和这个整数之间是否存在一个数是3和5的最小公倍数,如果存在最小公倍数,输出这个数,否则输出“n以内没有3和5的公倍数”
输入格式
输入一个正整数n
输出格式
输出最小公倍数数,或输出“n以内没有3和5的公倍数
运行代码:
num = int(input('输入一个正整数:'))
for i in range(1, num):if i % 3 == 0 and i % 5 == 0:print(i)break
else:print(f'{num}以内没有3和5的公倍数!')
运行结果:
项目实训11:
最大素数
描述
用户输入一个正整数 N,计算并输出不大于 N 的最大素数。
输入格式
输入一个正整数 N (N > 1)
输出格式
满足条件的素数
运行代码:
m = int(input('输入一个正整数:'))
for i in range(m, 1, -1):for j in range(2, i):if i % j == 0:breakelse:print(i)break
运行结果:
项目实训12:
四则运算
描述
用户输入两个数字,输出其加、减、乘、除运算的结果。
输入格式
输入两个数字
输出格式
分四行输出其加、减、乘、除运算的结果
运行代码:
a, b = map(int, input().split()) # 根据空格分隔
print(f'{a} + {b} = {a + b}')
print(f'{a} - {b} = {a - b}')
print(f'{a} * {b} = {a * b}')
print(f'{a} / {b} = {a / b}')
运行结果:
项目实训13:
正整数A+B
描述
题的目标很简单,就是求两个正整数A和B的和,其中A和B都大于0。稍微有点麻烦的是,输入并不保证是两个正整数。
输入格式
输入在一行给出A和B,其间以空格分开。问题是A和B不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。
注意:我们把输入中出现的第1个空格认为是A和B的分隔。题目保证至少存在一个空格,并且B不是一个空字符串。
输出格式
如果输入的确是两个正整数,则按格式A + B = 和输出。如果某个输入不合要求,则在相应位置输出?,显然此时和也是?。
运行代码:
ls = input().split(' ') # 切分结果一定是2个对象,列表try:
try:a = int(ls[0])if a <= 0:a = '? '
except ValueError:a = ' ? '
try:b = int(ls[1])if b <= 0:b = '? '
except ValueError:b = ' ?'
if a == '?' or b == ' ? ':print(f'{a}+{b}=? ')
else:print(f'{a}+{b}={int(a) + int(b)}')
运行结果:
项目实训14:
鸡兔同笼
大约在1500年前,《孙子算经》中就记载了这个有趣的问题。书中是这样叙述的:今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?
这四句话的意思是:有若干只鸡兔同在一个笼子里,从上面数,有35个头,从下面数,有94只脚。问笼中各有多少只鸡和兔?
请编一个程序,用户在同一行内输入两个整数,代表头和脚的数量,编程计算笼中各有多少只鸡和兔,假设鸡和兔都正常,无残疾。如无解则输出“Data Error!”
输入格式
在一行里输入两个整数,用空格分隔
输出格式
在一行里输出是鸡和兔的数量,输出格式如:有18只鸡,6只兔
如无解则输出“Data Error!”
输入:
35 94
输出:
有23只鸡,12只兔
输入:
100 5
输出:
Data Error!
运行代码:
head, foot = map(int, input().split(' '))
rabbit = (foot - head * 2) // 2
chicken = head - rabbit
if (head >= 0) and (foot >= 0) and (foot - 2 * head) % 2 == 0 and rabbit >= 0 and chicken >= 0:print(f'有{rabbit}只兔子', f'有{chicken}只鸡')
else:print('Data Error!')
运行结果:
项目实训15:
物不知数
“物不知数”出自《孙子算经》。题目为“今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?”意思是说有一些物品,不知道有多少个,3个3个数的话,还多出2个;5个5个数则多出3个;7个7个数也会多出2个。
假设物品总数不超过1000,请问这些个物品可能有多少个?
输入格式
输入一个正整数
输出格式
不超过输入数字且满足条件的物品个数
运行代码:
a = int(input('请输入一个正整数:'))
for i in range(1, a):if i % 3 == 2 and i % 5 == 3 and i % 7 == 2:print(i)
运行结果:
项目实训16:
运行代码:
a = int(input('请输入一个整数:'))
big, small = 1, 1
day = 0
big_s, small_s = 0, 0
while (a > 0):a = a - (big + small)if a < 0:a += (big + small)big_s += a / (big + small) * bigsmall_s += a / (big + small) * smalla = 0else:big_s += bigsmall_s += smallday = day + 1big = big * 2small = small / 2
print(day)
print(f'{big_s:.1f}', f'{small_s:.1f}')
运行结果:
项目实训17:
李白买酒
大诗人李白,一生好饮酒。一天,他提着酒壶,从家里出来,酒壶中有酒若干。他边走边唱:无事街上走,提壶去买酒,遇店加一倍,见花喝一斗,五遇店和花,喝光壶中酒,计算并输出壶中原有酒几斗?
运行代码:
wine = 0
for i in range(5):wine = wine + 1wine = wine/2
print(wine)
运行结果:
项目实训18:
宝塔上的琉璃灯
有一座八层宝塔,每一层都有一些琉璃灯,每一层的灯数都是上一层的二倍,已知共有765盏琉璃灯,计算并输出每层各有多少盏琉璃灯。
运行代码:
for first in range(0, 766):sum1 = 0ls = []for i in range(8):lamp = first * 2 ** ils.append(lamp)sum1 += lampif sum1 == 765:print(ls)break
运行结果:
项目实训19:
个人所得税计算器
目前我国个人所得税计算公式如下:
应纳个人所得税税额= (工资薪金所得 -五险一金 - 个税免征额)×适用税率-速算扣除数
2018年10月1日起调整后,个税免征额为5000元/月,7级超额累进个人所得税税率表如下:
全月应纳税所得额(含税级距) 税率(%) 速算扣除数
不超过3,000元 3 0
超过3,000元至12,000元的部分 10 210
超过12,000元至25,000元的部分 20 1,410
超过25,000元至35,000元的部分 25 2,660
超过35,000元至55,000元的部分 30 4,410
超过55,000元至80,000元的部分 35 7,160
超过80,000元的部分 45 15,160
请编写一个个人所税计算器,用户输入应发工资薪金所得、五险一金金额和个税免征额,输出应缴税款和实发工资,结果保留小数点后两位。当输入数字小于0或等于0时,输出“error”。
测试用例
输入(冒号前是提示性文字,冒号后的数字为用户输入)
请输入应发工资薪金金额:16000
请输入五险一金金额:4000
请输入个税免征额:5000
应缴税款490.00元,实发工资15510.00元。
输出
应缴税款490.00元,实发工资11510.00元。
运行代码:
salary = float(input("请输入应发工资薪金金额:")) # salary应发工资薪金所得
five_one_insurance_fund = float(input("请输入五险一金金额:")) # 五险一金
exenption = float(input("请输入个税免征额:")) # exenption个税免征额
taxable = salary - five_one_insurance_fund - exenption
if taxable < 0:tax = 0
else:if taxable <= 3000:tax_rate = 0.03deduction = 0elif taxable <= 12000:tax_rate, deduction = 0.1, 210elif taxable <= 25000:tax_rate, deduction = 0.2, 1410elif taxable <= 35000:tax_rate, deduction = 0.25, 2660elif taxable <= 55000:tax_rate, deduction = 0.3, 4410elif taxable <= 80000:tax_rate, deduction = 0.35, 7168else:tax_rate, deduction = 0.45, 15160tax = taxable * tax_rate - deduction
print(f'应缴纳税款{tax:.2f}元,实发工资{(salary-five_one_insurance_fund-tax): .2f}元')
运行结果:
项目实训20:
计算圆周率
中国是世界四大文明古国之一,在数千年的历史中,中华民族以不屈不挠的顽强意志、勇于探索的精神和卓越的聪明才智,谱写了波澜壮阔的历史画卷,创造了同期世界历史上极其灿烂的物质文明与精神文明。公元前一世纪出现的《周髀算经》是现存我国最古老的数学著作,其中叙述了勾股定理。公元一世纪的《九章算术》是对战国、秦汉时期我国人民所取得的数学系统总结,标志着我国古代数学体系的初步形成。
而究其具体内容,《九章算术》处理计算了大量复杂的问题。前面所列的九个分类中,包括了246个问题,以及202个“术”。其中有线型和圆型图形等多种几何图形的体积算法、面积算法等;有开平方术、开立方术;二项二次、二项三次等方程的解法;还有应用勾股定理解决问题的各种算法等等。从这些例子可看出其以计算为中心的特点。从数学内容上,九章算术不仅处理了大量复杂问题,而且包含了极限,分割,组合等重要的哲学思想和朴素的积分思想。
东西方两种不同数学发展意味着两种数学思想孕育在其中,一种是公理化思想,源于希腊。而整个中国古代数学贯穿了机械化思想,因中国古代数学是算法化,造就中国古代数学机械化思想更加适合数学的机械化,也更加适应计算机的发展,例如圆周率的计算,中国古代采用的割圆法就体现了迭代和极限的概念,方便计算机实现。
轮子是古代的重要发明,给人们的生产和生活带来了极大的方便。由于轮子的普遍使用,人们很自然地想到这样一个问题:一个轮子转一圈可以走多远?很显然,轮子越大,转动的距离越长,那么转动的距离与轮子的直径之间有什么关系呢?
人们最早用测量的方法来解决这个问题,经许多的人多次测量后,人们发现了圆的周长总是其直径的3倍多一些。在我国,现存的圆周率的最早记载是2000多年前的中国古算书《周髀算经》(约公元前2世纪)的中有“径一而周三”的记载,意即取π=3。汉朝时,张衡(78年—139年)得出π2/16=5/8,即π= ,约为3.162。
用测量的方法计算圆周率,圆周率的精确程度就取决于测量的精确程度,而众多的历史因素和许多实际的困难限制了测量的精度。
- 我国古代数学经典《九章算术》在第一章“方田”章中写到“半周半径相乘得积步”,为了证明这个公式,我国魏晋时期数学家刘徽于公元263年撰写《九章算术注》,在这一公式后面写了一篇1800余字的注记,这篇注记就是数学史上著名的“割圆术”。“割圆术”,则是以“圆内接正多边形的面积”,来无限逼近“圆面积”。刘徽形容他的“割圆术”说:割之弥细,所失弥少,割之又割,以至于不可割,则与圆合体,而无所失矣。这包含了求极限的思想。通过圆内接正多边形细割圆,并使正多边形的周长无限接近圆的周长,进而来求得较为精确的圆周率。
刘徽给出π=3.141024的圆周率近似值,刘徽在得圆周率=3.14之后,将这个数值和晋武库中汉王莽时代制造的铜制体积度量衡标准嘉量斛的直径和容积检验,发现3.14这个数值还是偏小。于是继续割圆到1536边形,求出3072边形的面积,得到令自己满意的圆周率。
图4.1 割圆法计算圆周率原理
设圆半径为1,圆内接正6边形边长也为1,计算正12边形的边长:
OC可用勾股定理计算:
新的边长AD值为:
编程实现割圆法计算圆周率,并输出分割不同次数时边数、圆周率值以及计算所得圆周率值与math库中的圆周率值的偏差。
输入:4
输出:
分割4次,边数为96,圆周率为3.14103195089051
相对math.pi偏差0.000560702699283322
输入:20
输出:
分割20次,边数为6291456,圆周率为3.141592653589663
相对math.pi偏差1.3011813848606835e-13
运行代码:
import mathdef cutting_circle(n): # n为分割次数side_length = 1 # 初始边长edges = 6 # 初始边数for i in range(n):height = 1 - math.sqrt(1 - (side_length / 2) ** 2)side_length = math.sqrt(height ** 2 + (side_length / 2) ** 2)edges = edges * 2pi = side_length * edges / 2return edges, piif __name__ == '__main__':times = int(input())print('分割{}次,边数为{},圆周率为{}'.format(times, *cutting_circle(times)))print(f'math库中的圆周率常量值为{math.pi}')
运行结果:
本章总结:
本章历时一个周完成,期间阳了,身体不舒服,断断续续写了一些,现在终于完成。本章有许多例题,学习过程中还是要勤加练习,多敲代码,做到理解并运用,然后才熟练掌握,感谢大家的支持!!!