python與概率簡單實(shí)踐——擲骰子
獨(dú)立擲一六面骰子(即點(diǎn)數(shù)為1,2,3,4,5,6),記錄每次擲出的點(diǎn)數(shù),當(dāng)點(diǎn)數(shù)大于20時(shí),停止投擲,問投擲次數(shù)的期望?
推而廣之,設(shè)面數(shù)為x,設(shè)定的點(diǎn)數(shù)和為y,滿足此題意的期望為多少?
不妨先將問題簡化一下,兩面的骰子,大于3停止,此時(shí)可以用人腦窮舉

都滿足題意
簡單計(jì)算可得期望為,投擲次數(shù)的加權(quán)平均,投擲次數(shù)越多,權(quán)值越小
(相當(dāng)于多投擲了,得到這個(gè)結(jié)果的概率也就小,本題中得到任一結(jié)果的概率為(1/2)^n,n為投擲次數(shù),2為骰子面數(shù)
(注意這些結(jié)果的概率和可不唯一,因?yàn)槲覀冎皇呛Y選出了一些合題意的結(jié)果,加權(quán)平均的真正目的是每種投擲情況出現(xiàn)的概率不一樣)
結(jié)果為:2.875)
我們考慮用計(jì)算機(jī)模擬
兩種思路:
1,暴力窮舉出所有情況,求加權(quán)平均
2,用生成隨機(jī)數(shù)的功能模擬投擲過程,用頻率逼近概率
思路1代碼如下:
#窮舉
import numpy as np
surface_number=2 #設(shè)定骰子面數(shù)
define_sum=3 #設(shè)定超過的值,大于此值即停止投擲
success_list=[] #記錄所有窮舉出合題意的結(jié)果
def ?method_of_exhaustion(lists): #此函數(shù)用來窮舉
? ?for i in range(surface_number,0,-1):
? ?#從面數(shù)到1循環(huán)(1到面數(shù)也可),覆蓋所有的情況
? ? ? ?if sum(lists)+i>define_sum:
? ? ? ? ? ?#原來的和加上某點(diǎn)超過規(guī)定值,則合適,記錄入succee_list
? ? ? ? ? ?success_list.append(lists+[i])
? ? ? ?else:
? ? ? ? ? ?method_of_exhaustion(lists+[i])
? ? ? ? ? ?#加上還不夠,加上此值后遞歸運(yùn)行次函數(shù)繼續(xù)擲骰子
medium=[]#從沒有擲骰子開始
method_of_exhaustion(medium)#運(yùn)行函數(shù)
#print(success_list) #顯示結(jié)果(因后續(xù)情況可能過于冗長,此處注釋掉)
#print(len(success_list)) #結(jié)果數(shù)
#需要求加權(quán)平均值的數(shù)據(jù)列表
elements = []
#對應(yīng)的權(quán)值列表
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)
'''
驗(yàn)證數(shù)據(jù)的正確性,可自行驗(yàn)證,此處注釋掉
每個(gè)單獨(dú)的結(jié)果需要滿足:
1,和大于規(guī)定值
2,除去最后一個(gè)數(shù),和小于規(guī)定值
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求加權(quán)平均

思路2代碼如下:
import random
#用隨機(jī)數(shù)模擬
experiment=10 #模擬次數(shù)
tries=5000#每次模擬實(shí)驗(yàn)次數(shù)
surface_number=2?#設(shè)定骰子面數(shù)
define_sum=3?? ?#設(shè)定和超過多少停止
for _ in range(experiment):
? ?success_list=[] #用于收集所有合法的結(jié)果
? ?for _ in range(0,tries):
? ? ? ?medium = [] #單次實(shí)驗(yàn)前要清空
? ? ? ?while True:
? ? ? ? ? ?value=random.randint(1,surface_number) #等概率生成隨機(jī)數(shù)
? ? ? ? ? ?medium.append(value)
? ? ? ? ? ?if sum(medium)>define_sum:#直到大于所規(guī)定值,停止投擲
? ? ? ? ? ? ? ?success_list.append(medium)
? ? ? ? ? ? ? ?break
? ?sums=0
? ?for i in success_list:
? ? ? ?sums+=len(i)
? ?print(sums/len(success_list))#期望值
我們選擇模擬10次,每次有5000組平行實(shí)驗(yàn),下面看輸出結(jié)果:

觀察到每次實(shí)驗(yàn)都很接近理論值
進(jìn)一步,我們可以任意修改surface_number,define_sum? ??
來任意設(shè)定骰子面數(shù)以及和超過多少停止
比如6面骰子,大于20停止(不包括20),仍是上述代碼,修改參數(shù)即可:


可以看到兩者十分接近
數(shù)學(xué)推導(dǎo)待續(xù)