欢迎光临散文网 会员登陆 & 注册

python与概率简单实践——掷骰子

2021-11-30 11:57 作者:与时代脱轨的级数  | 我要投稿

独立掷一六面骰子(即点数为1,2,3,4,5,6),记录每次掷出的点数,当点数大于20时,停止投掷,问投掷次数的期望?

推而广之,设面数为x,设定的点数和为y,满足此题意的期望为多少?


不妨先将问题简化一下,两面的骰子,大于3停止,此时可以用人脑穷举


穷举结果

都满足题意

简单计算可得期望为,投掷次数的加权平均,投掷次数越多,权值越小

(相当于多投掷了,得到这个结果的概率也就小,本题中得到任一结果的概率为(1/2)^n,n为投掷次数,2为骰子面数

(注意这些结果的概率和可不唯一,因为我们只是筛选出了一些合题意的结果,加权平均的真正目的是每种投掷情况出现的概率不一样)

结果为:2.875)

我们考虑用计算机模拟

两种思路:

1,暴力穷举出所有情况,求加权平均

2,用生成随机数的功能模拟投掷过程,用频率逼近概率

思路1代码如下:


#穷举
import numpy as np
surface_number=2 #设定骰子面数
define_sum=3 #设定超过的值,大于此值即停止投掷
success_list=[] #记录所有穷举出合题意的结果

def  method_of_exhaustion(lists): #此函数用来穷举
   for i in range(surface_number,0,-1):
   #从面数到1循环(1到面数也可),覆盖所有的情况
       if sum(lists)+i>define_sum:
           #原来的和加上某点超过规定值,则合适,记录入succee_list
           success_list.append(lists+[i])
       else:
           method_of_exhaustion(lists+[i])
           #加上还不够,加上此值后递归运行次函数继续掷骰子


medium=[]#从没有掷骰子开始
method_of_exhaustion(medium)#运行函数

#print(success_list) #显示结果(因后续情况可能过于冗长,此处注释掉)
#print(len(success_list)) #结果数

#需要求加权平均值的数据列表
elements = []
#对应的权值列表
weights = []
for i in success_list:
   length=len(i)
   elements.append(length)
   weights.append((1/surface_number)**(length))
a=np.average(elements, weights=weights)
print(a)

'''
验证数据的正确性,可自行验证,此处注释掉
每个单独的结果需要满足:
1,和大于规定值
2,除去最后一个数,和小于规定值
ha=0
for i in success_list:
   if sum(i)<=20:
       ha=1
   medium=i
   medium.pop()
   if sum(medium)>20:
       ha=1
print(ha)#ha为0说明正确
'''


其中用到了numpy求加权平均

显示结果的输出如下

思路2代码如下:


import random
#用随机数模拟

experiment=10 #模拟次数
tries=5000#每次模拟实验次数

surface_number=2 #设定骰子面数
define_sum=3    #设定和超过多少停止

for _ in range(experiment):
   success_list=[] #用于收集所有合法的结果
   for _ in range(0,tries):
       medium = [] #单次实验前要清空
       while True:
           value=random.randint(1,surface_number) #等概率生成随机数
           medium.append(value)
           if sum(medium)>define_sum:#直到大于所规定值,停止投掷
               success_list.append(medium)
               break

   sums=0
   for i in success_list:
       sums+=len(i)
   print(sums/len(success_list))#期望值


我们选择模拟10次,每次有5000组平行实验,下面看输出结果:

输出结果

观察到每次实验都很接近理论值

进一步,我们可以任意修改surface_number,define_sum    

来任意设定骰子面数以及和超过多少停止

比如6面骰子,大于20停止(不包括20),仍是上述代码,修改参数即可:

随机数法运行结果
穷举法结果(暴力算法可能与严格值有些许误差)

可以看到两者十分接近

数学推导待续

python与概率简单实践——掷骰子的评论 (共 条)

分享到微博请遵守国家法律