不同編程語言擅長的領(lǐng)域
熟練地掌握編程描述概率問題,不僅幫助我們理解概率中極易混淆的概念,而且能直接驗(yàn)證概率問題。同時(shí),運(yùn)用編程在解決概率問題又能令孩子們體驗(yàn)到編程的魅力。今天的任務(wù)不僅需要能夠?qū)⑷蝿?wù)拆解為子任務(wù),而且,大喵老師給出一個極易誤導(dǎo)的錯誤寫法,令孩子們有機(jī)會洞察概率的本質(zhì)。
情景導(dǎo)入:假設(shè)丁丁貓組織戶外STEM活動為期8天,準(zhǔn)備階段分工有一項(xiàng)是列清單,出行和活動需要的準(zhǔn)備的東西。mcree同學(xué)負(fù)責(zé)統(tǒng)籌預(yù)判每個需要考慮的因數(shù)。首先,天氣是重要的影響因素。活動準(zhǔn)備兩套方案,一套是雨天的活動方案,另一套是晴天的活動方案。
Phil同學(xué)找到當(dāng)?shù)氐奶鞖鈹?shù)據(jù)看9月份戶外地點(diǎn)的降雨概率是25%,晴天的概率是75%,mcree委托phil同學(xué)判斷兩個事件發(fā)生的概率:
A、8天的活動期間全部晴天的概率和
B、前4天晴天,第5天轉(zhuǎn)雨天的概率
Phil同學(xué)在這兩者之間比較,A和B 誰出現(xiàn)的概率更大?思路梳理:數(shù)學(xué)角度看,兩個方案在前四天都是雨天,所以兩個方案前四天的概率是相同的。問題就轉(zhuǎn)換為:第5天轉(zhuǎn)為晴天的概率,與接下來連續(xù)4天都是雨天的概率比較誰更大?課堂的游戲規(guī)則是分兩組分工,一組數(shù)學(xué)思路解;另一組運(yùn)用編程思維轉(zhuǎn)換為可編程計(jì)算的任務(wù)**。每個人都可以在老師啟發(fā)下開始:1、你的直覺是什么結(jié)果?
2、如何理解連續(xù)發(fā)生的事件和單一事件的概率?
3、某一天下雨的概率和連續(xù)幾天下雨的概率之間的關(guān)系
Ada同學(xué)經(jīng)過思考,任務(wù)可以用random函數(shù),隨機(jī)生成某一天的天氣
下面是列表包含了3個s,s= sunny晴天和1個雨天:r = rain
非常直觀的表達(dá)雨天的概率是25%
import random
sun_rain = ['r','s','s','s']
today = random.choice(sun_rain)
Ada受到以上啟發(fā),想出一個辦法模擬連續(xù)n天的天氣隨機(jī)結(jié)果:
前4天連續(xù)晴天,第5天下雨的事件A的概率
連續(xù)8天都是晴天,即事件B的概率
事件A:for循環(huán)100000次,每一次random函數(shù)生成的“s"或"r"拼接為字符串,運(yùn)用count函數(shù)計(jì)算字符串中"rrrrs"的出現(xiàn)的次數(shù)累積起來;
事件B:for循環(huán)100000次,每一次random函數(shù)生成的“s"或"r"拼接為字符串,運(yùn)用count函數(shù)計(jì)算字符串中"ssssssss"的出現(xiàn)次數(shù)累積起來;
代碼如下:
import random
def randomSR():
sun_rain = ['r','s','s','s']
s = ''
for _ in range(10000):
s += random.choice(sun_rain)
prob_A = ''.join(s).count("rrrrs")
prob_B = ''.join(s).count("ssssssss")
return prob_A,prob_B
print('the 1st:',randomSR())
結(jié)果:
the 1st: (311, 2805)
結(jié)果是不是違反直覺!連續(xù)8天都是晴天的概率竟然遠(yuǎn)遠(yuǎn)大于連續(xù)4天晴天且第5天下雨的概率!
Ada疑惑地將結(jié)果告訴大喵老師后,大喵老師并沒有直接告訴Ada,她的算法是正確還是錯誤
但是,大喵老師請同學(xué)們一起討論Ada的算法!
同學(xué)們都陷入長時(shí)間的思考 ... ... 有同學(xué)感到哪里不對勁,但指不出究竟問題在哪兒?
大喵老師給出一個隨機(jī)生成的長度是60的字符串,分別運(yùn)用兩種算法得到不同的結(jié)果!
第一種寫法是Ada的思路,統(tǒng)計(jì)連續(xù)字符串出現(xiàn)的次數(shù);
第二種寫法是字符串最左邊開始滑動窗口,窗口的大小分別是5和8,循環(huán)截至?xí)r,統(tǒng)計(jì)
兩個字符串出現(xiàn)的次數(shù)!
# 第一種寫法是Ada的算法
ls = '' #初始化字符串
sun_rain = ['r', 's', 's', 's']
for d in range(60): #模擬60天
ls += random.choice(sun_rain)
print('ls:',ls)
print('five_day:',ls.count("ssssr"))
print('eight_day:',ls.count("ssssssss"))
輸出結(jié)果
five_day: 4
eight_day: 3
第二種寫法是老師的推薦:
# 每一次從相同位置開始,分別切片5和8試試看
# 滑動向右第 i 天開始分別切片:
# 前4天晴天,第5天雨天,切5個長度[i : i+6]
# 連續(xù)8天是晴天,切8個長度:[i : i+8]
five_day, eight_day = 0 , 0
for i in range(len(ls) - 8):
if ls[i:i + 5] == 'ssssr':
five_day += 1
elif ls[i:i + 8] == "ssssssss":
eight_day += 1
print("five_day:",five_day,"eight_day:",eight_day)
five_day: 4 eight_day: 9
比較兩種結(jié)果,連續(xù)8天都是晴天的次數(shù)由3次,變?yōu)?次,為什么同一隨機(jī)樣本產(chǎn)生不同的結(jié)果?
課堂將展開討論。
Ada依照第二種思路改變算法后:
def randomSR_2nd():
sun_rain = ['r', 's', 's', 's']
eight,fifth = 0,0
s = ''
for _ in range(100000):
s += random.choice(sun_rain)
#print(s)
for i in range(len(s)-8):
if s[i:i+5] == 'ssssr':
fifth += 1
elif s[i:i+8] == "ssssssss":
eight += 1
return fifth,eight,round(eight/fifth,5)
print('the 2nd:',randomSR_2nd())
輸出的新結(jié)果:
the 2nd: (7880, 9996, 1.26853)
輸出結(jié)果的解讀是,連續(xù)8天都是晴天的概率大于連續(xù)4天晴天且第5天是雨天的概率!
而且,前者是后者的1.26853倍,保留5位小數(shù);
大喵老師留給大家一個問題:從數(shù)學(xué)角度如何解釋以上結(jié)果?
print(round(0.75**4 / 0.25,5))
1.26562
數(shù)學(xué)解法的思路:
前4天都是晴天的概率是 0.75 ** 4, 第5天是晴天的概率是 0.25
后4天都是晴天的概率也是0.75 ** 4,那么前后比較得到:
0.75 ** 4 / 0.25 = 1.26562