淺析C語言中的rand函數和srand函數(一)


我們在編程實現算法的過程中,往往需要使用到隨機數。由於計算機是一台以邏輯為基礎的機器,沒法做到真正的隨機(大概量子計算機可以?)。所以計算機生成的是偽隨機數,供我們使用。

我們使用C語言的rand函數,生成的也是偽隨機數。

一個簡單的示范如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <time.h>
 4 
 5 int
 6 main(int argc, char** argv)
 7 {
 8     // 以機器當前的時間來構造生成偽隨機數的"種子" 。 
 9     srand((unsigned int)time(NULL));
10     int i;
11     // 打印10個偽隨機數 
12     for (i = 0; i < 10; i++) {
13         
14         printf("%d ", rand());
15     }
16     printf("\n");
17     
18     system("pause");
19     return 0;
20 }

 

很顯然,如果不使用第九行的srand函數,那么我們的程序每次打印的10個偽隨機數序列是一樣的,在本機上始終是41, 18467, 6334, ......。這是由於C語言是利用linear congruential generator作為生成器來生成偽隨機數,但是這個生成器生成偽隨機數,需要一個“種子”來進行運算。而如果我們僅僅調用rand函數,那么我們始終使用的是C語言自己設置的固定的“種子”來生成偽隨機數,所以生成的偽隨機數的序列肯定是一模一樣的咯。

當我們使用srand,以時間為參數,為rand提供一個不一樣的“種子”,那么由於每次的“種子”都不一樣,當然每次的偽隨機數的序列都不一樣。

但是從代碼實現中,我們不能清楚地看出來srand函數提供的“種子”如何就被rand函數用上了。

從ISO C99標准(ISO/IEC 9899:1999(E))當中的偽隨機數一節(7.20.2 Pseudo-random sequence generation functions),我們可以看到一個簡明的可移植的實現樣例:

 1 static unsigned long int next = 1;
 2 
 3 int rand(void) // RAND_MAX assumed to be 32767
 4 {
 5     next = next * 1103515245 + 12345;
 6     return (unsigned int)(next/65536) % 32768;
 7 }
 8 
 9 void srand(unsigned int seed)
10 {
11     next = seed;
12 }

 

在這個樣例中,“種子”為靜態內部變量next,初始值為1。如果我們不使用srand來更新next,很顯然我們每次調用程序生成的偽隨機數都是一樣的(next從1開始)。如果我們在程序中用srand來更新next,那么我們每次運行程序,就給next初始化以不同的值,於是就能夠得到不一樣的偽隨機數序列。

 

但是,rand函數和srand函數的實現真如樣例這般簡單嗎?

放到下篇再寫吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM