隨機三維單位向量的生成演算法如何做到均勻分布?

演算法1:直角坐標系,x, y, z均取[-1, 1]內的隨機數,然後單位化。

演算法2:球坐標系,theta取[0, 2Pi]內的隨機數,phi取[-Pi/2, Pi/2]內的隨機數,然後轉化為直角坐標。

問題:

1.
兩種演算法能滿足均勻分布的要求嗎?比如對演算法1,是否45度對角線方向的向量出現的概率會更高?對演算法2,是否球面兩極對應向量有更高概率?

2.
兩種演算法是否具有同等的均勻性,若不是,哪種的均勻性更好?


前些天我思考過一個問題,如何將頂點隨機分布到球面上。其實這與題主是同一個問題。想到的方法也是題主提出的這兩個。我呢,數學證明什麼的已經渣了,但我會動手。將65536個頂點分布到球面上,然後畫出來,看它均勻與否。

我寫了一個軟體YChaos生成混沌圖像,用它可以顯示這些頂點。下面的切圖看著是二維的,但在軟體中這些頂點是在三維空間中。

演算法1:直角坐標系,x, y, z均取[-1, 1]內的隨機數,然後單位化。

x=rand2(-1, 1)
y=rand2(-1, 1)
z=rand2(-1, 1)
r=sqrt(x*x + y*y + z*z)
x=x/r
y=y/r
z=z/r

不均勻,在六個頂點及八條邊上,頂點更為集中。演算法2:球坐標系,theta取[0, 2Pi]內的隨機數,phi取[-Pi/2, Pi/2]內的隨機數,然後轉化為直角坐標。

theta=rand2(0, 2*PI)
phi=rand2(-PI/2, PI/2)
x=sin(phi)*sin(theta)
y=cos(phi)*sin(theta)
z=cos(theta)

不均勻,在上下兩個頂點上,頂點更為集中。趙永峰提出的方法

u=rand2(0, 1)
v=rand2(0, 1)
theta = 2*PI*u
phi = arccos(2*v - 1)
x=sin(theta)*sin(phi)
y=cos(theta)*sin(phi)
z=cos(phi)

這是均勻的.


黑魔法來了。對標準正態分布採樣三次,生成隨機數 x, y, z,則歸一化後的向量 (x, y, z) 符合要求。完全避免了昂貴的三角函數。我在實際工作中一直用的這個。


這問題我正巧做過……

第一種太costy,二維的隨機變數居然sample3個數,不經濟。

第二種不是均勻的,因為球面上的度規不是平的,點會在極點附近聚集。

有一個最簡單的辦法。sample兩個(0,1)上的均勻分布隨機變數uv,然後計算:

	heta=2pi u

phi=arccos(2v-1)

就對了。

參見Sphere Point Picking -- from Wolfram MathWorld

====================

P.S. 投影三維高斯(正態)分布、三維均勻分布舍選、以及MathWorld上另外兩種使用了其他變換的方法都是可行的。具體哪個快需要按照你的需求、工作環境、隨機數產生器的效率、手邊庫的情況來跑profile決定。

P.S.2. 這種方法還有個trick,你不一定真的需要算acos。如果你只關心生成的點的笛卡爾坐標,2v-1直接給你cosphi,sinphi相應地算一下就好了,省去幾次調用三角函數的時間。最終需要調用2次三角函數和1次sqrt。

P.S.3. 說到profile,今天正好跑了一個:

我想知道為啥我的Ratio-of-Uniforms比Box-Muller還慢……難道是這個隨機數生成器太慢……


Sphere Point Picking -- from Wolfram MathWorld

@Cong Qiao 的是對的,證明見鏈接提到的參考文獻。


你要生成單位長度的三維向量的話

第一種不是均勻的,第二種是均勻的


第一種演算法是均勻的,第二種演算法從結果上來看會是球心位置的密度大一些,不過這在球坐標條件下依然可以視為均勻。


兩種都不均勻,第一種如你所說,會集中在對角線附近;第二種的話,均勻分布的密度函數應當是sin	heta d	heta dphi


推薦閱讀:

為了還李林老師一個清白,請大家把手上的證據集中在這個問題下?
怎麼理解代數幾何概念 motive?
如何設計演算法計算一個超長數列的和?
如何解答這道關於數論的題目?
傅立葉級數和傅立葉變換是什麼關係?

TAG:演算法 | 數學 | 概率 |