rand函數的實現原理

jopen 9年前發布 | 14K 次閱讀 rand

rand函數的實現原理

rand函數產生的是偽隨機數,也就是說它不是一個真實的隨機數。

那么偽隨機數是怎么實現的呢?原理大概如下:

如果約定:a1=f(seed),an+1=f(an)那你可以行到一個序列:a1,a2,a3...an,那么要制作一個偽隨機函數rand,只需要讓它每調用一次就返回序列的下一個元素就行。

就相當于第1次調用rand返回a1,第2次返回a2,…,第n次返回an,這樣每次調rand都能拿到一個不同的數,只要整個序列的規律不明顯,整個函數看起來就是隨機的。

現在計算機上的rand函數都是用這樣的原理實現的,這里的seed被稱為“隨機數種子”。

但這里有一個問題,如果seed不變,那我們每次調用rand函數獲取的序列都是相同的。這就會造成有的程序跑一遍退出后,再重新跑一遍,兩次的輸出結果是相同的。所以我們還需要一個接口去設置seed值,這個接口就是srand函數。

linux下的rand是用類似下面的代碼實現的:

static unsigned long next = 1;

/ RAND_MAX assumed to be 32767 / int myrand(void) { next = next * 1103515245 + 12345; return((unsigned)(next/65536) % 32768); }

void mysrand(unsigned seed) { next = seed; }</pre>

myrand、mysrand分別對應rand和srand,但實際的rand實現會復雜一些。

使用rand函數的一個問題

有些人使用rand函數時,因為初始化時沒有調用srand會造成程序每次運行輸出結果都相同:http://ask.csdn.net/questions/174871

如果你沒有調用srand設置隨機數種子,seed的默認值會是0,而seed為0時所決定的序列是固定的,而第一次調用rand()就是返回這個固定序列里的第1個元素,那它的值也是固定的,自然你的程序每次輸出都一樣了。

所以正確的寫法應該是程序初始化時用srand設置不同的隨機數種子(只需要設置一次),例如srand(time(NULL)),但要注意,time(NULL)的值是隔1秒才改變一次的,必要情況下可以考慮使用精度更高的時間函數,如gettimeofday。

下面這段程序,只要你不是在同一秒內執行兩次,每次輸出結果都是不一樣的:

#include <stdio.h>

include <stdlib.h>

include <time.h>

int main() { srand(time(NULL)); // 設置隨機數種子 for (int i = 0; i < 10; i++) { printf("%u\n", rand()); } getchar(); return 0; }</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!