C/C++產生隨機數


C/C++產生隨機數用到兩個函數rand() 和 srand()。

一. 不指定范圍產生隨機數

在C語言中,我們一般使用 <stdlib.h> 頭文件中的 rand() 函數來生成隨機數,它的用法為:

int rand (void);

// void 表示不需要傳遞參數。

C語言中還有一個 random() 函數可以獲取隨機數,但是 random() 不是標准函數,不能在 VC/VS 等編譯器通過,所以比較少用。

  • rand() 會隨機生成一個位於 0 ~ RAND_MAX 之間的整數。

RAND_MAX 是 <stdlib.h> 頭文件中的一個宏,它用來指明 rand() 所能返回的隨機數的最大值。C語言標准並沒有規定 RAND_MAX 的具體數值,只是規定它的值至少為 32767。在實際編程中,我們也不需要知道 RAND_MAX 的具體值,把它當做一個很大的數來對待即可。

#include <stdio.h>

#include <stdlib.h>

int main(){

int a = rand();

printf("%d\n",a);

return 0;

}

運行結果舉例:

41

多次運行上面的代碼,你會發現每次產生的隨機數都一樣,都是41,這是怎么回事呢?為什么隨機數並不隨機呢? 

實際上,rand() 函數產生的隨機數是偽隨機數,是根據一個數值按照某個公式推算出來的,這個數值我們稱之為“種子”。種子在每次啟動計算機時是隨機的,但是一旦計算機啟動以后它就不再變化了;也就是說,每次啟動計算機以后,種子就是定值了,所以根據公式推算出來的結果(也就是生成的隨機數)就是固定的。

    • 重新播種,然后再調用rand()

我們可以通過 srand() 函數來重新“播種”,這樣種子就會發生改變。srand() 的用法為:

void srand (unsigned int seed);//里面是參數類型,seed不能直接用在程序中,只是說明,可以是函數

它需要一個 unsigned int 類型的參數。在實際開發中,我們可以用時間作為參數,只要每次播種的時間不同,那么生成的種子就不同,最終的隨機數也就不同。使用 <time.h> 頭文件中的 time() 函數即可得到當前的時間(精確到秒),就像下面這樣:

srand((unsigned)time(NULL));

上述代碼修改如下后,沒啟動一次程序,隨機數都不一樣。

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main() {

int a;

srand((unsigned)time(NULL));

a = rand();

printf("%d\n", a);

return 0;

}

多次運行程序,會發現每次生成的隨機數都不一樣了。但是,這些隨機數會有逐漸增大或者逐漸減小的趨勢,這是因為我們以時間為種子,時間是逐漸增大的,結合上面的正態分布圖,很容易推斷出隨機數也會逐漸增大或者減小。

    • 生成一定范圍內的隨機數

我們可以利用取模的方法:

int a = rand() % 10; //產生0~9的隨機數,注意10會被整除

如果要規定上下限:

int a = rand() % 51 + 13; //產生13~63的隨機數

最后給出產生 13~63 范圍內隨機數的完整代碼:

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main(){

int a;

srand((unsigned)time(NULL));

a = rand() % 51 + 13;

printf("%d\n",a);

return 0;

}

  • 連續生成隨機數

很容易想到的一種解決方案是使用循環,每次循環都重新播種,請看下面的代碼:

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main() {

int a, i;

//使用for循環生成10個隨機數

for (i = 0; i < 10; i++) {

srand((unsigned)time(NULL));

a = rand();

printf("%d ", a);

}

return 0;

}

運行結果舉例:
6 6 6 6 6 6 6 6 6 6

運行結果非常奇怪,每次循環我們都重新播種了呀,為什么生成的隨機數都一樣呢?
這是因為,for 循環運行速度非常快,在一秒之內就運行完成了,而 time() 函數得到的時間只能精確到秒,所以每次循環得到的時間都是一樣的,這樣一來,種子也就是一樣的,隨機數也就一樣了。

解決:

srand((unsigned int )time(NULL));//保證每次執行不一樣

for (i = 0; i < 10; i++) { 

                     a = rand();

                     printf("%d ", a);

}//循環內每次a也不同

二. 指定范圍產生隨機數,產生0到某個數的隨機數

沒有現成的函數,但是可以通過取余得到。

#include<stdio.h>
#include<stdlib.h>
#define Random(x) (rand() % x) //通過取余取得指定范圍的隨機數
int main()
{
        int i;
        int dis=100; //產生[0, dis)之間的隨機數,注意不包括dis
        for(i=0; i<10; i++)
        {
                printf("%d\n", Random(dis));
        }
        return 0;
}

注意一個問題:以上兩個程序每次執行產生的結果是相同的,既是個偽隨機數。rand()產生隨機數與具體的種子有關,當不特意用srand()獲取種子時,種子的默認值為1,因此需要用srand()函數產生不同的種子,同上.

為了產生不同的種子值,通常用時間作為參數值。例如對於一,修改程序如下:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
        int i;
        srand((int)time(NULL)); //每次執行種子不同,生成不同的隨機數
        for(i=0; i<10; i++)
        {
                printf("%d\n", rand()); //如果執行太快,不到一秒鍾,10個隨機數是相通的,但是每次執行是不同的

         }

         return 0;

}

經測試,與上面注釋是不同的,在一次程序執行中 的for循環,rand()不一樣,加上種子,每一次執行程序后的數 也不一樣。意味着在循環外加上 srand((int)time(NULL)),可以得到兩個不同,即每一次執行程序不一樣,循壞內也不一樣,從而做到隨機。

作者那么解釋,說循環內10個相同,難道是這計算機執行慢?


免責聲明!

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



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