利用Python破解生日悖論問(wèn)題
一、前言
別問(wèn)我為啥題目是英文,因?yàn)?hellip;高大上(bushi。
刷視頻的時(shí)候偶然刷到了一個(gè)關(guān)于生日悖論的,當(dāng)場(chǎng)就覺(jué)得不可思議,直到上網(wǎng)查了查……
誒,怎么是真的?
這玩意兒居然還被設(shè)置到了密碼攻擊學(xué),就很離譜的。
密碼攻擊我倒是沒(méi)那個(gè)肝,就…檢驗(yàn)一下這個(gè)悖論的合理性吧。
本文將會(huì)對(duì)生日悖論進(jìn)行詳細(xì)的講解,寫(xiě)作不易,支持一下?。ㄈf(wàn)年不變客套話)
二、生日悖論是什么
可能有很多人不了解這個(gè)悖論,讓我們先了解一下。
生日悖論,就是23個(gè)人在一個(gè)房間,期間必然有兩個(gè)人生日相同的概率為50%,30個(gè)人的話概率是70%,60個(gè)人甚至上升到99%。
這本來(lái)不應(yīng)該是悖論,但是讓人感覺(jué)十分不合理,違反直覺(jué),故此叫做悖論。
大家肯定會(huì)問(wèn):一共就23個(gè)人,不應(yīng)該是23/365的幾率嗎?怎么可能呢?
其實(shí),是因?yàn)?hellip;好吧我也不知道,要是一個(gè)小學(xué)生都知道這就不叫悖論了。
反正這種想法肯定是錯(cuò)誤的,百度上說(shuō)因?yàn)槭请S機(jī)的23個(gè)人,大腦不擅長(zhǎng)處理非線性函數(shù),其實(shí)23個(gè)人就有很多種組合。
我們換一種想法。假設(shè)有23個(gè)人,那么如果想讓生日不相同,第一個(gè)人就可以是365天的任意一個(gè)就是365/365,而第二個(gè)人就必須是其他364個(gè)就是364/365,最后到了第23個(gè)人就是343/365。
最后我們把這些概率一乘,1一減,才是真正的概率。
三、公式破解
和上面說(shuō)的想法一樣,我們可以用公式去破解這個(gè)悖論。
公式:
p為生日相同的概率,用1減去就是生日不相同的概率,這個(gè)我們是可以求的,如上所述。
思路:用上面的公式代入進(jìn)去,先求分母相乘的結(jié)果,冪運(yùn)算就行。
之后求分子相乘結(jié)果,for循環(huán)遞減人數(shù),結(jié)果相乘,結(jié)束。
之后用分子除以分母得到概率,用1一減,結(jié)果保留三位小數(shù),加百分號(hào),初始化變量之后再次檢測(cè)。
he=1#初始化變量 he2=1#初始化變量 while 1:#死循環(huán) try:#錯(cuò)誤捕捉 people=int(input())#獲取人數(shù) except:#如果發(fā)生錯(cuò)誤 print("請(qǐng)輸入正確")#提示錯(cuò)誤 else:#如果沒(méi)有發(fā)生錯(cuò)誤 he=365**people#計(jì)算下面的所有365相乘,冪運(yùn)算 jian=365#初始化遞減的變量 for xh in range(people):#for循環(huán)遞減 he2=he2*jian#計(jì)算 jian-=1#jian自減,模擬公式分子的遞減 print(round((1-he2/he),3),"%")#輸出保留三位小數(shù)后的結(jié)果 he2=1#初始化變量
這就是公式破解的方法。
注釋已經(jīng)放上去了,自己看。
四、隨機(jī)數(shù)破解
這種破解方法就是隨機(jī)生成輸入的人數(shù),檢測(cè)他們的生日是否相同。
思路:首先創(chuàng)建一個(gè)函數(shù),封裝產(chǎn)生隨機(jī)數(shù)和檢測(cè)是否有重合項(xiàng)的代碼。
之后死循環(huán),獲取人數(shù)信息并且進(jìn)行多次實(shí)驗(yàn)取平均值,輸出概率。
比較列表的每一項(xiàng)是否相同,還用上for循環(huán),肝了半個(gè)小時(shí),突然想到集合可以去重,比較前后長(zhǎng)度是否有改變就行了…
import random as r#導(dǎo)入隨機(jī)數(shù)模塊且命名r birthday=[]#保存不同生日的列表 shuliang=0#初始化變量 def jiancha():#創(chuàng)建函數(shù)來(lái)新建生日和檢查是否重合 global shuliang,birthday#全局兩個(gè)變量 for xh in range(people):#循環(huán)人數(shù)次 birthday.append(r.randint(1,365))#添加隨機(jī)數(shù)生日 if len(birthday)!=len(set(birthday)):#集合去重后與之前長(zhǎng)度不一樣就是有重合項(xiàng) shuliang+=1#數(shù)量加一 birthday.clear()#清空列表birthday while True:#死循環(huán) try:#異常捕獲 people=int(input())#獲取人數(shù) for xh2 in range(1000):#進(jìn)行1000次檢測(cè)求平均值 jiancha()#調(diào)用函數(shù) print(shuliang/1000)#求平均值 shuliang=0#初始化變量 except:#如果發(fā)生錯(cuò)誤 print("請(qǐng)輸入正確的數(shù)字")#提示
注釋也放上去了自己看。
五、添加功能:dict儲(chǔ)存及改變方式
接下來(lái),我們添加一個(gè)功能:用dict儲(chǔ)存不同人數(shù)時(shí)的概率,并且先用字典保存所有再在字典里查找人數(shù)。
我們要用到字典方法:setdefault。再回顧一下詳解2:
用法:返回括號(hào)里鍵的值,如果沒(méi)有這個(gè)鍵就在字典里添加這個(gè)鍵,值為None,如果又填了一個(gè)值就是要添加的值。
還有g(shù)et,也是輸出對(duì)應(yīng)的值,沒(méi)有則返回第三個(gè)值。
聽(tīng)不懂?看就完了!
import random as r#導(dǎo)入隨機(jī)數(shù)模塊且命名r birthday=[]#保存不同生日的列表 zidian={}#保存人數(shù)和概率的字典 shuliang,find=0,0#初始化變量 def jiancha():#創(chuàng)建函數(shù)來(lái)新建生日和檢查是否重合 global shuliang,birthday#全局兩個(gè)變量 for xh in range(people):#循環(huán)人數(shù)次 birthday.append(r.randint(1,365))#添加隨機(jī)數(shù)生日 if len(birthday)!=len(set(birthday)):#如果有重合項(xiàng) shuliang+=1#數(shù)量加一 birthday.clear()#清空列表birthday while find<100:#大于等于100才退出循環(huán) try:#異常捕獲 find=int(input("要進(jìn)行多少次檢測(cè)?數(shù)量越高準(zhǔn)確度越高但是時(shí)間會(huì)變長(zhǎng),至少100次否則程序會(huì)出錯(cuò)"))#獲取次數(shù) if find<100:#如果find小于100 raise(ValueError)#拋出異常 except:#如果異常 print("請(qǐng)正確輸入,查看自己輸入格式是否正確及數(shù)值是否大于99")#提示 for people in range(1,366):#每一個(gè)人數(shù) for xh2 in range(find):#進(jìn)行find次檢測(cè)求平均值 jiancha()#調(diào)用函數(shù) if people%20==0:#如果可以被20整除 print("等待進(jìn)度:",round(people/365*find,2),"%")#安慰進(jìn)度條 zidian.setdefault(people,str(shuliang)+"%")#字典添加人數(shù)和概率 shuliang=0#初始化變量 zidian2=str(zidian)#zidian2為zidian的字符串形式 while True:#死循環(huán) try:#異常捕獲 cha=int(input("請(qǐng)輸入房間有多少個(gè)人,輸出全部請(qǐng)輸入114514"))#詢問(wèn)人數(shù)或者全部輸出 if cha==114514:#如果選擇全部輸出 print(zidian2[1:-1])#截取字符串來(lái)去大括號(hào) print("冒號(hào)前面是人數(shù),冒號(hào)后面是概率")#提示語(yǔ) else:#如果選擇截取 print(zidian.get(cha,"請(qǐng)輸入1到365位"))#輸出對(duì)應(yīng)的value,如果沒(méi)有則提示范圍 except:#如果錯(cuò)誤 print("請(qǐng)輸入正確")#提示
代碼解析還是看注釋。
到此這篇關(guān)于利用Python破解生日悖論問(wèn)題的文章就介紹到這了,更多相關(guān)Python生日悖論內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python利用dlib獲取人臉的68個(gè)landmark
這篇文章主要介紹了python利用dlib獲取人臉的68個(gè)landmark,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11

利用Pycharm + Django搭建一個(gè)簡(jiǎn)單Python Web項(xiàng)目的步驟

Python實(shí)現(xiàn)不規(guī)則圖形填充的思路

一起來(lái)學(xué)習(xí)Python的元組和列表

Python如何通過(guò)Flask-Mail發(fā)送電子郵件

簡(jiǎn)單示例解析python爬蟲(chóng)IP的使用(小白篇)

python獲得linux下所有掛載點(diǎn)(mount points)的方法