求一個數學公式:要求生成一個可控制分布的隨機數?

比如:生成一個隨機值 rand (範圍是 1-100)。rand中出現小的值概率很高,但大的值的概率很低。希望大神給一個具體的公式。隨機值用rand替代就行。最好可以用代碼實現,比如PHP Python等,謝謝!


給定一個累積分布函數( cumulative distribution function, CDF)Y=F(X),只要能求出其反函數X=F^{-1}(Y),就能把均勻分布的隨機數Y in [0,1]映射至X。這稱為 Inverse transform sampling。


Random sampling (numpy.random)

numpy.random 已經實現了從定義好的分布中抽樣的函數,

比如

beta(a, b[, size]) Draw samples from a Beta distribution.
binomial(n, p[, size]) Draw samples from a binomial distribution.
chisquare(df[, size]) Draw samples from a chi-square distribution.
dirichlet(alpha[, size]) Draw samples from the Dirichlet distribution.
exponential([scale, size]) Draw samples from an exponential distribution.
f(dfnum, dfden[, size]) Draw samples from an F distribution.
gamma(shape[, scale, size]) Draw samples from a Gamma distribution.
geometric(p[, size]) Draw samples from the geometric distribution.
gumbel([loc, scale, size]) Draw samples from a Gumbel distribution.


假設樓主取的是1-100的整數,100的概率比99大一倍,99比98大一倍,

那麼按1 為基準,

總和SUM= 1+2+ 4 + 2^99 =2^100-1

那麼 隨機取rand(1,SUM), 如果在2^30-1到2^31範圍之間,那麼就是取到30。簡單的公式是log(rand(1,SUM))/log2


舍選法。

不用特別擔心計算次數:


獻一下丑,有錯誤勞煩指出!

恰好做畢設碰到了這個問題,與大家分享下。

假設我們獲得了每個值的概率,然後對每個值的概率進行累加,將每次累加結果統一放在一個數軸上表示。我們取10個值來說明問題,如下圖:

[i]表示第i個值,橫坐標軸(0-0.1)就代表 [1]的概率;(0.5-0.75)代表第 [7]的概率;(0-0.75)代表 [1]到 [7]的概率累加和。

接下來,比如說在matlab里,使用rand()函數,產生一個範圍為0-1均勻分布的隨機數,假如圖中產生的數為0.65,它落在(0.5-0.75)這個區間,而這個區間代表著 [7]的概率。於是,我們判定將 [7]拿出來作為本次按概率篩選的結果。

附matlab的代碼

%其中max_column值的個數,prob代表每個

%值的概率,prob_array代表概率累加和

%largest_cumulative_prob代表概率累加最大值

for j=1:max_column -1

prob_array(j+1) = prob_array(j)+prob(j);

end

largest_cumulative_prob=prob_array(max_column);

%largest_cumulative_prob和prob_array需要做

%歸一化,代碼里沒有做

choice = rand() * largest_cumulative_prob;

low = 1;

high = max_column;

while (high&>(low+1))

middle = (high+low)/2;

middle = floor(middle);

if (choice &> prob_array(middle))

low = middle;

else high = middle;

end

end

%最後取出low作為本次篩選結果

%這裡就不解釋了,其思想和上面圖中一樣的

這個方法適用於離散的數,對於連續的數我還不清楚怎麼處理,個人猜想可能會用到概率密度?望大神解答!


看過一點ndndsim的源碼。裡面生成zipf分布的方法很有趣。希望能給題主參考。給定累積分布函數和範圍比如是1-50。算出累計分布函數在1到50函數值存在數組裡。然後用一個均勻分布 生成一個隨機數。然後依次和五十個分布函數值比較。返回下標。當然返回下標這一點可以隨要求變化。


100/rand(1,100)


rand(1,rand(1,rand(1,100)))這樣你看行不行


推薦閱讀:

Python的for使用問題?
怎麼樣算是學會一門編程語言?
你們開始是如何學習編程的?
看代碼千行,不如手寫一行,是否在理?為何?
通過什麼可以了解一個程序員/黑客的真實水平?

TAG:Python | PHP | 數學 | 編程 | 隨機數 |