前言
题目
在本练习中,我们将尝试做一个实验。如果你掷硬币100次,并在每次正面时写下“H”,在每次反面时写下“T”,就会创建一个看起来像“T T T T T H H H H T T”这样的列表。如果你要求一个人进行100次随机掷硬币,你可能会得到交替正反的结果,例如“H T H T H H T H T T T”,(对人类而言)这看起来是随机的,但在数学上并不是随机的。即使极有可能发生在真正随机的硬币翻转中,人类也几乎永远不会写下连续6个正面或6个反面。可以预见,人类在随机性方面会很糟糕。
编写一个程序,查找随机生成的正面和反面列表中出现连续6个正面或6个反面的频率。你的程序将实验分为两部分:第一部分生成随机选择的“正面”和“反面”值的列表,第二部分检查其中是否有连胜。将所有这些代码放入一个循环中,重复该实验10 000次,这样我们就可以找出掷硬币中包含连续6个正面或反面的百分比。作为提示,函数调用random.randint(0,1)将在50%的时间返回0值,在另外50%的时间返回1值。
你可以从以下模板开始:
import random
numberOfStreaks = 0
for experimentNumber in range(10000):
# Code that creates a list of 100 'heads' or 'tails' values.
# Code that checks if there is a streak of 6 heads or tails in a row.
print('Chance of streak: %s%%' % (numberOfStreaks / 100))
当然,这只是一个估计,但是10 000是一个不错的样本量。一些数学知识可以为你提供准确的答案,并且可以节省编写程序的麻烦,但是有些程序员在数学方面稍弱。
一、实现思路
题目看似冗长,耐心读完后不难发现,其实第二段已经告诉读者如何实现,只需要我们顺藤摸瓜,细化到每一步,即可实现此题目。
- random模块随机生成0和1
- 计算硬币正反面的概率
- 计算连续六个正面或反面的‘频率’
二、代码实现
1.计算抛硬币正反的概率
代码如下(示例):
import random
# 列表存放正反面的结果
coin = []
# 初始化正反面次数为0,设置循环的次数time
head = 0
tail = 0
time = 100
#循环即抛硬币
for i in range(time):
#random随机生成0和1,代表正和反
n = random.randint(0, 1)
#设置判断条件,将正反面次数存放到变量,并存放到列表中
if n == 0:
head += 1
coin.append(n)
elif n == 1:
tail += 1
coin.append(n)
print('正面出现的概率', head/time)
print('反面出现的概率', tail/time)
2.计算6正或6反的频率
代码如下(示例):
# 记录本次硬币面和上一次是否相同,x正,y反
x = 0
y = 0
#计算6正6反各自概率的合
a = 0
b = 0
#循环比较
for i in range(len(coin)):
#设置判断条件,二元操作符的第一个条件coin[i]==0,即从正面开始,如果第i-1次和第i次相同,则x加1,继续执行直到x==5(6面相同执行5次即可判断)
if coin[i] == 0 and coin[i-1] == coin[i]:
x += 1
elif coin[i] == 1 and coin[i-1] == coin[i]:
y += 1
#计算6正6反各自的概率和,当x==5时归0,重新判断
if x == 5:
a += 1/len(coin)
x = 0
elif y == 5:
b += 1/len(coin)
y = 0
#6正6反出现的频率
print(a/len(coin))
print(b/len(coin))
总结
难点:
- 如何判断硬币本次和下次是否相同(经查询后得知)
需要注意的点:
- 用append()方法将数据存放到列表中;我使用的是+=操作,但这样会改变数据类型。
- 计算6次正面相同或反面相同,只需要判断5次
存疑的点:
- 不确定判断6正6反的条件是否正确(自己感觉是正确的hhh)
- 如若条件正确,可能存在一个小bug,当从coin[0]开始时会和coin[-1]比较,也就是coin[99],考虑过加while判断
- 6正6反概率总和最大值为0.01?