偽隨機數概念在我大學一年級接觸C語言基礎的時候就聽說過,並熟練掌握C語言中rand()函數的使用方法。不過,當時我對偽隨機數的認識基本也就停留在百度百科那種小白水平,最多就知道老師說我們用的隨機數是假的,是通過某種算法實現的。最近學習計算物理學講到Monte Carlo方法時,通過課本和互聯網才算真正意義上理解了什么是偽隨機數。借此文好好總結一下吧!
一、隨機數的分類
在計算物理學中,隨機數被准確地分成了三類:真隨機數、准隨機數、偽隨機數。那么這三種的區別是什么呢?拷貝一段書上的定義(我覺得寫的挺好的⊙﹏⊙,其實是懶得想別的表述方式):
1)真隨機數:產生的數不可預計,也不可能重復產生兩個相同的真隨機數序列。真隨機數只能通過某些隨機的物理過程來產生,如放射性衰變、電子設備的熱噪聲等。
2)准隨機數:其隨機數序列不具備隨機性質,僅僅是用它來處理問題能夠得到正確的結果。(老實說,准隨機數我目前也沒准確理解,讀者有好的例子請@我)
3)偽隨機數:通過某種數學公式或者算法產生的數值序列。雖然在數學意義上偽隨機數是不隨機的,但是如果能夠通過統計檢驗,可以當成真隨機數使用。
二、偽隨機數算法
偽隨機數產生的方法有個逼格挺高的名字---偽隨機數發生器。偽隨機數產生器中最最最基礎的思想是均勻分布(當然這不是唯一的思路)。一般來說,只敢說"一般來說",因為我也不敢百分百肯定,如今主流的編程語言中使用的隨機數函數基本采用這種均勻分布思想,而其中最常用的算法就是"線性同余法"(有着很多的別名,不過我喜歡用這個名字,原因你懂的→_→)。不BB別的算法,直接介紹線性同余法。
1. 什么是線性同余法?
對於計算機科學專業的學生來說,八成會接觸一門課,叫作《離散數學》。里面有一章專門介紹初等數論,而線性同余法作為產生均勻型偽隨機數的算法,有大概一頁的論述(真是一個悲劇(-_-メ))。當然,可能很多人在初中或者之后的數學競賽中學過初等數論,線性同余法當然也一定是有過接觸的。
線性同余法基於如下線性同余方程組
用於產生均勻型偽隨機數的線性同余產生器(與上面的方程符號沒有對應關系)
其中,a為"乘數",b為"增量",m為"模數",x0為"種子數"。
如果產生的是區間實在(0,1)之間的,則只需要每個數都除以m即可,即取
2. 線性同余法產生均勻型偽隨機數需要注意什么?
2.1)種子數是在計算時隨機給出的。比如C語言中用srand(time(NULL))函數進行隨機數種子初始化。
2.2)決定偽隨機數質量的是其余的三個參數,即a,b,m決定生成偽隨機數的質量(質量指的是偽隨機數序列的周期性)
2.3)一般b不為0。如果b為零,線性同余法變成了乘同余法,也是最常用的均勻型偽隨機數發生器。
3. 高性能線性同余法參數取值要求?
3.1)一般選取方法:乘數a滿足a=4p+1;增量b滿足b=2q+1。其中p,q為正整數。 PS:不要問我為什么,我只是搬運工,沒有深入研究過這個問題。
3.2)m值得話最好是選擇大的,因為m值直接影響偽隨機數序列的周期長短。記得Java中是取得32位2進制數吧。
3.3)a和b的值越大,產生的偽隨機數越均勻
3.4)a和m如果互質,產生隨機數效果比不互質好。
三、偽隨機數代碼實現
本文采用Java代碼實現偽隨機數算法(當然不是調用Java庫函數,也不是抄它的代碼)。產生序列的均勻性可以通過Matlab或者導入Excel作圖直觀檢驗。
1 package monteCarlo; 2 3 public class MonteCarlo { 4 private static final int MAXN = 1 << 20; 5 private int[] x; 6 7 public MonteCarlo() { 8 x = new int[MAXN]; 9 } 10 11 public void rand() { 12 x[0] = (int)(Math.random()*100 + 1); // 隨機種子(可以用日期產生) 13 /* 保證m與a互質 */ 14 int m = MAXN; 15 int a = 9; // a = 4p + 1 16 int b = 7; // b = 2q + 1 17 18 System.out.println(x[0]); 19 /* 取前1w個數*/ 20 for(int i = 1; i < 10000; ++i) { 21 x[i] = ( a * x[i-1] + b ) % m; 22 System.out.println(x[i]); 23 } 24 } 25 26 public static void main(String[] args) { 27 MonteCarlo mc = new MonteCarlo(); 28 mc.rand(); 29 } 30 }
四、均勻性檢驗結果
統計運算太麻煩了,直觀上圖。反正這圖我沒有發現明顯的規律。因此這種偽隨機數在一定條件下是可以滿足隨機性性質的。而以前我取a=5,b=1時有部分點在一條斜線上分布,這就不滿足咯。
(⊙o⊙)總算完成了偽隨機數算法(一)線性同余法,舒了一口氣。文章構思原創,當然知識點...你懂的,不過轉載還是希望尊重一下我勞動的小成果。