posted on 2023年5月24日
by jinchao
最近在工作中遇到這麼乙個問題:
在遊戲場景中有乙個怪物生成點,這個生長點產生的怪物均勻分布在半徑為r的圓形內,這個隨機演算法應該如何生成?看起來很簡單,隨手寫了乙個:
#define
rand
((float
)rand()/
rand_max
)void
get_random_pos
(float
center_x
, float
center_y
, float
radius
, float&x
, float& y
) 但寫的過程中,直覺告訴我,這麼寫肯定是有問題的,試想,如果以北京為例,如果所有居住在北京的人都報出自己家和天安門的距離,那麼這些資料肯定不是均勻分布的,因為居住在五環附近的人數肯定要大於居住在二環附近的人數,於是用mathamatica實驗一下:
果然,這麼寫是不對的,網上查了一下,這個問題還真是有人研究過,說應該把所獲得的隨機數開平方一下,實驗一下:
但是,這個開平方背後的數學原理究竟是什麼呢?抽空翻了下概率書,原來,其中的道理並不複雜,這裡涉及到概率裡的乙個基本概念,累計分布函式(cumulative distribution function),簡稱cfd,它的定義如下:
設有乙個隨機變數x
,它的取值範圍是從負無窮到正無窮,如果把它的值小於x
的概率表達為乙個函式f(x
),那麼這個函式就稱為x
的累計分布函式f(
x)=p
(x≤x
) 以最為常見的均勻分布概率為例,設均勻分布的隨機變數x
的取值範圍是[a,
b],那麼它的累計分布函式以及函式影象是f(
對於乙個累計分布函式,符合以下規律
回到我們的問題中,假設怪物產生的範圍的半徑為r
,隨機產生乙隻怪物時,它和中心的距離是乙個隨機變數x
,顯然,對於怪物均勻分布的情況,x
落在半徑為x
的圓內的概率,等於半徑為x
小圓和半徑為x
的大圓的面積之比
也就是說f(
x)=p
(x≤x
)=x2
/r2
現在我們手頭上只有均勻概率的隨機數產生器,要想產生這麼個隨機數需要用到乙個很巧妙的運算,就是反函式。設隨機變數
u是乙個均勻分布在[0,1]之間的隨機數,另乙個隨機變數 x=
f−1(
u),現在我們需要證明
x的累計分布函式是 f(
x)證明如下 p
(x≤x
)=p(
f−1(
u)≤x
)=p(
u≤f(
x))=
f(x)
初看起來有點複雜,其實在下面的圖上可以很直觀的理解這個過程:
這是利用了 f(
x)是單調遞增函式的特性,在我們的問題中, f(
x)的反函式可以表達為 f
−1(u
)=ru
−−√
所以最終的演算法可以寫成
#define
rand
((float
)rand()/
rand_max
)void
get_random_pos
(float
center_x
, float
center_y
, float
radius
, float&x
, float& y
) tagged 數學, 程式, 演算法
演算法 均勻的生成圓內的隨機點
演算法 1 設半徑為 r x r ast cos theta y r ast sin theta 其中 0 leqslant r leqslant r t 為0 1均勻分布產生的隨機數,r sqrt t ast r theta 2 pi ast t,t sim u 0,1 證明 url 下面的演算法...
乙個均勻繫結 cpu 的 shell
有時,由於架構設計或其他業務本身特點原因,導致有些應用是由cpu很不均衡 處理集中在乙個cpu是上 白白浪費其他cpu在睡覺。乙個簡單辦法就是繫結到多個cpu 繫結 cpu 是乙個不錯技巧,但是不是殺手鐗,一般能提高10 效能 更好地辦法是優化架構,對於網路處理性程式,繫結網絡卡中斷。這裡分享乙個小...
隨機生成乙個根據引數指定的隨機數
在開發過程中隨時都可以遇到隨機數,但是有時候往往達不到自己意願,在這裡我將自己寫的乙個方法整理出來,大家一起交流!desciption 隨機生成乙個根據引數指定的隨機數 str 生成隨機碼位數 arg 1 生成全數字,2 生成數字字母混合 private static string makepass...