思考与练习:
P99
4.1 正确
4.2 错误。分支结构(if/else)不能向已经执行过的语句部分跳转,循环结构(while/for)可以向已经执行过的语句部分跳转。
4.3 A
流程图的基本元素:起止框,判断框,处理框,输入/输出框,注释框,流向线,连接点。
4.4 B
P103的拓展问题:
对任意一个守卫说:“你去问问另一个守卫,哪扇门通往天堂。”按照他说的反着做。
假设说谎的是A,实话实说的是B,你让A去问B,B说对了,A在传达的时候,就会把实话说成假话;相反,你去让B问A,A说的是假话,B就会如实的把A说的假话告诉你。
P104
4.5 错误
4.6 错误
4.7 正确 在语法上是正确的,但在逻辑上不通。x<=y<=z相当于x<=y and y <= z。但是最后的结果是两者的与,只会输出True或False。
4.8 B
4.9 D
score = eval(input("请输入成绩:")) #使用eval(input('请输入数字:'))来获取用户输入的数字,单用input是字符串
if score >= 60.0:
grade = 'D'
elif score >= 70.0:
grade = 'C'
elif score >= 80.0:
grade = 'B'
elif score >= 90.0:
grade = 'A'
print(grade)
P107
4.10
因为这里的判断是由小向大进行判断的,在执行第8行前就已经在第六行判断过是否小于18.5,只有大于等于18.5才能走到第八行。第十行同理。
4.11
这里的原因参照上面4.7的解释。x24<=28<25等价于24<=28 and 28<25,即true and false,这样结果就是false
4.12
续行的作用:如果一行太长了想分行,在第一行后加空格\,就可以把剩下的写到第二行。
4.13
我认为正确,for循环主要是循环次数确定,而while循环不管循环次数是否确定都可以。(暂认正确,不对再改)
4.14
错误
4.15
错误 在编程中死循环并不是一个需要避免的问题,相反,在实际应用中,经常需要用到死循环。例如,我们使用的Windows操作系统下的窗口程序中的窗口都是通过一个叫消息循环的死循环实现的。在单片机、嵌入式编程中也经常要用到死循环。(另外一个很简单的想法,没有益处的东西在历史的更迭中一定会被舍弃,是不会被留存下来使用的。既然留下来了就一定有它的作用)
4.16 D
4.17 B
P113
4.18
(1)
import random
for i in range(10):
print(random.randint(0,100),end = ' ') #randint(a,b)生成一个[a,b]之间的随机整数
import random
list = [] #创建一个空列表
for i in range(101):
if i%2 != 0:
list.append(i) #100以内所有奇数放入列表list
print(random.choice(list)) #choice(seq)从序列中随机返回一个元素
#运行结果:53(随机选择,每次结果不一样,仅供参考)
(3)
import random
list = ['a','b','c','d','e','f','g','h','i','j'] #创建一个abcdefghij列表
for i in range(4):
print(random.choice(list)) #choice(seq)从序列中随机返回一个元素
#运行结果:
# d
# d
# c
# j
(4)
import random
list = ['apple','pear','peach','orange'] #创建一个['apple','pear','peach','orange']列表
print(random.choice(list)) #choice(seq)从序列中随机返回一个元素
#运行结果:
# peach
random库的常用函数:
P116
4.19
P115 6.1代码仅修改随机点个数
from random import random
from math import sqrt
from time import perf_counter #因为博主的python的版本是3.8,移除了clock,所以转用了perf_counter代替
DARTS = 2**25 #增加随机点个数到2的25次方
hits = 0.0
perf_counter()
for i in range (1,DARTS+1):
x,y = random() , random()
dist = sqrt(x**2+y**2) #每个随机点距离原点的直线距离
if dist <= 1.0:
hits = hits+1 #在半径为1.0的圆内随机点的个数
pi = 4 * (hits/DARTS)
print("Pi值是{}".format(pi))
print("运行时间是:{:.5f}s".format(perf_counter()))
#运行结果:
# Pi值是3.1417593955993652
# 运行时间是:24.38070s
4.20
设置随机种子即可
注:pi的值每次都一样,但运行时间根据当前电脑状态的不同会发生改变
from random import random
from random import seed
from math import sqrt
from time import perf_counter #因为博主的python的版本是3.8,移除了clock,所以转用了perf_counter代替
DARTS = 2**25 #增加随机点个数到2的25次方
hits = 0.0
seed(1)#设置随机种子为1
perf_counter()
for i in range (1,DARTS+1):
x,y = random() , random()
dist = sqrt(x**2+y**2) #每个随机点距离原点的直线距离
if dist <= 1.0:
hits = hits+1 #在半径为1.0的圆内随机点的个数
pi = 4 * (hits/DARTS)
print("Pi值是{}".format(pi))
print("运行时间是:{:.5f}s".format(perf_counter()))
#运行结果:
# Pi值是3.1413724422454834
# 运行时间是:24.72988s
P120
4.22
try和except这两个关键字合成“try-except”语句,是基本的异常处理机制。except捕获并处理异常。
在“try-except”语句的基础上,将其延伸为“try-except-else-finally”语句。else代码只有在try中语句正常执行完毕且没有出现异常的情况下执行。finally代码块无论出不出错都会被执行。
4.23
利用“try-except”
4.24
if判断,把所有的情况都用if语句表达出来
(个人想法,不包对)
P121:
程序练习题:
4.1 猜数游戏。在程序中预设一个0~9之间的整数,让用户通过键盘输入所猜的数,如果大于预设的数,显示“遗憾,太大了”;小于预设的数,显示“遗憾太小了”,如此循环,直至猜中该数,显示“预测N次,你猜中了!”,其中N是用户输入数字的次数。
import random
X = random.randint(0,9)
n = 0
while True:
n = n + 1
x = eval(input("请输入0~9之间的一个整数:"))
if x > X :
print("遗憾,太大了")
elif x < X :
print("遗憾,太小了")
else:
print("预测{}次,你猜中了".format(n))
break
运行结果:
4.2 统计不同字符的个数。用户从键盘输入一行字符,编写一个程序,统计并输出其中英文字符、数字、空格和其他字符的个数。
写完了发现看错题了,统计其中,英文字符,不是中英文字符╮(╯▽╰)╭ 就这吧,只统计英文就把判断中文字符的去掉就行了。
str = input("请输入一行字符:")
a,b,c,d = 0,0,0,0
for i in str:
if 'a'<=i<='z' or 'A'<=i<='Z' or '\u4E00'<=i<='\u9FFF': #Unicdoe 4E00~9FFF表示中文
a = a+1 #a代表中英文字符个数
elif '0'<=i<='9':
b = b + 1 #b代表数字个数
elif i == ' ':
c = c + 1 #c代表空格个数
else: #d代表其他字符
d = d + 1
print("在这行字符中英文字符{}个,数字{}个,空格{}个,其他字符{}个".format(a,b,c,d))
运行结果:
4.3 最大公约数计算。从键盘接收两个整数,编写程序求出这两个整数的最大公约数和最小公倍数(提示:求最大公约数可用辗转相除法,求最小公倍数则用两个数的积除以最大公约数即可)
def gcd(m,n): #辗转相除法求公约数
r = m % n
while r != 0:
m = n
n = r
r = m % n
return n
m , n = eval(input("请输入两个整数(用逗号隔开):"))
x = gcd(m,n)
y = m*n/x
print("{},{}的最大公约数是{},最小公倍数是{}".format(m,n,x,y))
运行结果:
辗转相除法:
4.4 猜数游戏续。改变程序练习题4.1,让计算机能够随机产生一个预设数字,范围在0~100之间,其他游戏规则不变。
(与4.1相比仅改变第二行随机数范围及输入提示)
import random
X = random.randint(0,100)
n = 0
while True:
n = n + 1
x = eval(input("请输入0~100之间的一个整数:"))
if x > X :
print("遗憾,太大了")
elif x < X :
print("遗憾,太小了")
else:
print("预测{}次,你猜中了".format(n))
break
运行结果:
4.5 猜数游戏续。对于程序练习题4.4程序,当用户输入的不是整数(如字母,浮点数等时),程序会终止执行退出。改变该程序。当用户输入出错是给出“输入内容必须为整数!”的提示,并让用户重新输入。
加入了try - except异常处理
import random
X = random.randint(0,100)
n = 0
while True:
n = n + 1
try: #增加异常处理语句
x = eval(input("请输入0~100之间的一个整数:"))
except NameError:
print("输入内容必须为整数!")
x = eval(input("请输入0~100之间的一个整数:"))
if type(x) == float: #若为浮点数退出程序
break
else:
if x > X :
print("遗憾,太大了")
elif x < X :
print("遗憾,太小了")
else:
print("预测{}次,你猜中了".format(n))
break
运行结果:
**4.6 羊车门问题。有3扇关闭的门,一扇门后面停着汽车,其余门后面是山羊,只有主持人知道每一扇门后面是什么。参赛者可以选择一扇门,在开启它之前,主持人会开启另外一扇门,露出门后面的山羊,然后允许参赛者更换自己的选择。请问:参赛者更换选择后能否增加猜中汽车的机会?——这是一个经典问题。
请使用random库对这个随机事件进行预测,分别输出参赛者改变选择和坚持选择选择获胜的机率。
问题分析:**
当参赛者转向另一扇门而不是维持原先的选择时,有三种可能的情况,全部都有相等的可能性(1/3):
参赛者挑山羊一号,主持人挑山羊二号。转换将赢得汽车。
参赛者挑山羊二号,主持人挑山羊一号。转换将赢得汽车。
“参赛者挑汽车,主持人挑羊一号。转换将失败。”,和“参赛者挑汽车,主持人挑羊二号。转换将失败。”此情况的可能性为:1/3 * 1/2+1/3 * 1/2 = 1/3
分析可得转换选择后,获胜的机率是2/3。即不转换获胜的机率是1/3。
另一种想法,当参赛者不转换原来的选择,则必须一开始就选中停着汽车的那扇门,机率为1/3。即转换获胜的机率为2/3。
用代码实现:(这里用的是第二种想法)
import random
total = 10000#测试次数
win1 = 0 #不转换的胜利次数
win2 = 0 #转换的胜利次数
for i in range(total):
choice = random.randint(1,3) #从1到3中任选一个数,每个数代表一个门
car = random.randint(1,3) #车所在的门
if choice==car:
win1 += 1
else:
win2 += 1
print("若不更改门,获胜概率为{:.3}%.".format((win1/total)*100))
print("若更改门,获胜概率为{:.3}%.".format((win2/total)*100))
运行结果:
理论上讲,次数越多,越接近2/3。
4.7 请用异常处理改造实例1,使其能够接收并处理用户的任何输入。
好家伙,找实例1找了半天,在第二章P34,温度转换。
我觉得不用改造,按照实例1的源代码,如果输入格式不对就直接运行结束了,没找到错误,也就不会异常捕获。可能是我知识量太少,实在找不到异常类型。