2013/3/31

【C語言】亂數

  閒來無事突然好奇random()函數是不是真的能產生很均勻的數值來,就寫了個小程式將產生的亂數值做餘數處理分配到四個變數,在將最後結果印出來,結果竟然十分均勻,直接先看程式內容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char **argv) {
 int value[4] = {0, 0, 0, 0};
 int max = INT_MAX;

 srand(time(NULL));
 for(int i = 0; i < max; i++) {
  value[rand() % 4] += 1;
 }

 for(int i = 0; i < 4; i++) {
  printf("%d => %d\n", i, value[i]);
 }

 printf("Total: %d\n", max);
 return  0;
}

執行幾次結果大致相同
1
2
3
4
5
0 => 536870911
1 => 536870912
2 => 536870912
3 => 536870912
Total: 2147483647

母體設小一點就比較不那麼均勻

1
2
3
4
5
0 => 14
1 => 10
2 => 9
3 => 17
Total: 50

  說實話這樣的結果其實讓我有點懷疑亂數太過造假,也就是說顯得不自然,雖然這樣的結果符合機率告訴我們的只要母體夠大在公平的條件下大家機會是相等的,不過軟體產生的亂數本來就是依據演算公式不斷疊代產生,因此對於這樣的結果好像也就不需要太意外了!

PS. 環境說明

  • 編譯器:Visual Studio Express 2012 for Windows Desktop
  • 執行環境:Windows 7 SP1

2013/04/02 補充
  同樣程式碼放在Linux下跑,得出來的亂數值有比較符合原先預期的結果,先看執行結果:
第一次執行
1
2
3
4
5
0 => 536849545
1 => 536888948
2 => 536882094
3 => 536863060
Total: 2147483647
第二次執行
1
2
3
4
5
0 => 536877294
1 => 536896031
2 => 536864732
3 => 536845590
Total: 2147483647
不曉得linux下的library在實作此亂數函數時是否也有把一些硬體外在環境因素也加入演算,像是/dev/random/dev/urandom有把硬體訊號元的變因加入亂數產生演算因子,所以才會得到比較貼近實際的結果?