如何編程產生泊松分布的隨機數?

我是一名大二學生,概率論只學了一半,剛學完連續型隨機變數聯合分布函數。我們VBA老師留了一項作業:生成泊松分布的隨機數,手頭工具只能使用Excel自帶的rnd()函數。請問生成的原理是啥?想了好久都想不明白該怎麼做,希望有人能指點一下下,要的是思路和原理,不是代碼,謝謝!

已經百度到的信息:

1. rnd()是均勻分布函數;

2. 有人給的原理貌似是:

x1*x2*...*xn&<=exp^(-lambda)&<=x1*x2*...*x(n+1)

貌似n還是啥就是生成的隨機數,但是這個式子我完全看不懂。

求現階段我能理解的答案。。。非VBA亦可,之前也學過C++,只要是原理就成。


你說的這個問題叫做Poisson過程,其產生的思路如下:

1,從Uniform(1)的均勻分布出發,用Inverse CDF 方法產生一系列獨立的指數分布(參數為lambda)隨機數X_i sim exp(lambda)

2,記Y=X_1+X_2+...+X_k。如果Y>t,則停止,輸出k-1;若否,則繼續生成X_{k+1},直到Y>t為止;

3,重複過程2。

容易證明,輸出的一系列整數k就滿足服從參數為mu=lambda t的Poisson分布。


提供一個生成離散型隨機數的一般思路,以泊松分布P(X=k)=frac{lambda ^k}{k!} e^{-lambda } ,k=0,1,...為例:

非常感謝 @王贇 Maigo的提醒,我把原來的廢話都刪了,思路很簡潔。

只要生成一個0到1之間的隨機數,然後看泊松分布的前幾項和剛好大於這個隨機數就行了。

下面是vba代碼,這個可以擴展到其他的離散型隨機變數,但運行效率不理想:

Function PoissonRand(lambda As Double) As Integer
Dim rand As Single
Dim k As Integer
Randomize
rand = Rnd
k = 0
Do While rand &> WorksheetFunction.POISSON(k, lambda, True)
k = k + 1
Loop
PoissonRand = k
End Function

這裡直接用了POISSON函數可以直接獲得累積概率。

根據 @王贇 Maigo優化版,去除階乘計算提升效率,可讀性稍受影響,且其他離散型隨機變數很難復用:

Function PoissonRand(lambda As Double) As Integer
Dim rand As Single
Dim k As Integer
Dim p As Single
Dim sump As Single

Randomize
rand = Rnd
k = 0
"p(0)化簡
p = 1 / Exp(lambda)
Do While rand &> sump
k = k + 1
"從p(k)轉換到p(k+1)
p = p * lambda / k
sump = sump + p
Loop
PoissonRand = k
End Function

另外,由於浮點數精度、rnd偽隨機性和試驗次數較少等原因,隨機數和理論值存在偏差。

我隨機了10000組PoissonRand(20):

數據源:


Poisson distribution

Wikipedia 上有 Knuth 給出的演算法,其中λ是參數

algorithm poisson random number (Knuth):
init:
Let L ← e?λ, k ← 0 and p ← 1.
do:
k ← k + 1.
Generate uniform random number u in [0,1] and let p ← p × u.
while p &> L.
return k ? 1.

不要問我為什麼, 凡是Knuth說的都對!

---------------------------

如果將 L都取一個對數,就變成了

algorithm poisson random number (Knuth):
init:
Let L ← ?λ, k ← 0 and p ← 0.
do:
k ← k + 1.
Generate uniform random number u in [0,1] and let p ← p + ln(u).
while p &> L.
return k ? 1.

而 ln(u) 正是產生指數分布。

當然,我們喜歡看正數一些,對 L加個負號,就和頂樓的方法一樣啦。

algorithm poisson random number (Knuth):
init:
Let L ← λ, k ← 0 and p ← 0.
do:
k ← k + 1.
Generate uniform random number u in [0,1] and let p ← p - ln(u).
while p &< L. return k ? 1.


Ross, Sheldon M.

Simulation


一個比較理想的辦法是構造一個函數Y=f(X),如果輸入的隨機變數X服從一個分布(例如[0,1)的均勻分布),那麼輸出的隨機變數Y服從我們需要的分布。但是這個問題里泊松分布是離散的,數學上這個函數比較難寫出來,所以可以用另一個辦法。

考慮泊松分布的物理意義,是一個泊松過程在一個定長時間內的事件發生次數。

假如說你在一個公交車站,一輛公交車到下一輛公交車之間的間隔如果是參數為lambda的指數分布,那一個單位時間內到達公交車的數量服從泊松分布。

餘下你就模擬一下就好了。


最快的是不是還是分段rejective sampling


Inverse transform sampling


看scipy的源碼,不只播送分布,各種分布都有,想看什麼看什麼


推薦閱讀:

你在學習 C++ 的過程中遇到的最大的困難是什麼?
作為一名程序員,你在編程的道路上一路走來都接觸過什麼語言?對你的程序員之路有什麼影響?
C printf #用法?
windows10 為什麼不把POSIX完整支持了?
為什麼多數外掛都用易語言?

TAG:數學 | 編程 | 概率論 | 泊松分布 |