偽隨機數C語言程式設計

ARM的程式設計師敲著詩歌的夢發表於2020-04-04

在程式設計中,有時會用到隨機數。本文介紹在 Linux 程式設計環境下,如何生成偽隨機數。

什麼是偽隨機數

偽隨機數是通過一個確定性的演算法計算出來的“似乎”是隨機的數序,因此偽隨機數實際上並不隨機。在計算偽隨機數時,假如初始值不變的話,那麼偽隨機數的數序也不變。

偽隨機數的優點

要產生真正的隨機數,必須使用專門的裝置,比如熱噪訊號、量子力學效應、放射性元素的衰退輻射,或使用無法預測的現象等。而偽隨機數計算比較簡單,不需要外部特殊硬體的支援,因此在電腦科學中偽隨機數依然被使用。

偽隨機數的缺點

由於偽隨機數不是真的隨機數,在有些方面它們不能被使用。例如在密碼學中使用偽隨機數要小心,因為其可計算性是一個可以攻擊的地方。統計學、蒙特·卡羅方法上使用的偽隨機數也必須挑選週期極長、隨機性夠高的隨機函式,以確保計算結果有足夠的隨機性。

利用 rand() 函式生成偽隨機數

函式原型:

//需要包含標頭檔案 <stdlib.h>  
int rand(void);

Linux 中的rand()函式會返回一隨機數值,其範圍在0RAND_MAX 間。這裡的RAND_MAX定義在stdlib.h中(如下圖的128行所示),值為 2147483647(=2^31-1)。
這裡寫圖片描述

以下例子利用 rand() 函式生成偽隨機數。

#include <stdlib.h>
#include <stdio.h>

#define RAND_NUM    5

int main(int argc, char *argv[])
{
    for(int i=0; i< RAND_NUM; ++i)
        printf( "%d ", rand() );

    printf("\n");
    return 0;
}

編譯後連續執行兩次,結果是:

$ ./rand
1804289383 846930886 1681692777 1714636915 1957747793 
$ ./rand
1804289383 846930886 1681692777 1714636915 1957747793

為什麼會這樣呢?

計算機產生的偽隨機數是通過遞推的方法得來的,必須要有一個初始值,也就是通常所說的種子。如果不對種子進行初始化,那麼計算機會使用一個預設值。由於兩次執行中初始值一樣(都是預設值),遞推公式也一樣,所以才有完全一樣的偽隨機序列。

對於rand()函式,如果未設隨機數種子,rand()在被呼叫時會自動設隨機數種子為1

要想避免這種結果,就需要在每次程式執行時對種子進行初始化 ,且初始值不一樣(比如到目前為止經過的時間 )。

獲取當前時間(以秒計算)

函式原型:

// 需要包含標頭檔案 <time.h>   
time_t time (time_t* timer);

time_t其實是一個長整形。

time_t time (time_t* timer)函式的用法是:

當引數為NULL的時候,返回從1970年1月1日0時0分0秒到此時的秒數;當引數不為NULL的時候,不僅返回從1970年1月1日0時0分0秒到此時的秒數,還把返回值儲存到引數指向的time_t型別的變數裡。

設定種子

函式原型:

// 需要包含標頭檔案 <stdlib.h> 
void srand (unsigned int seed);

srand函式把種子值作為引數。結合函式time_t time (time_t* timer),我們可以這樣設定種子:

srand( (unsigned int)time(NULL) );

參考程式碼

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define RAND_NUM    5

int main(int argc, char *argv[])
{
    srand( (unsigned int)time(NULL) );

    for(int i=0; i< RAND_NUM; ++i)
        printf( "%d ", rand()%100 );

    printf("\n");
    return 0;
}

實驗結果如下:

$ ./rand
61 71 64 35 13 
$ ./rand
50 11 83 43 69 
$ ./rand
68 32 35 94 83 

【完】

參考資料

http://txgcwm.github.io/blog/2013/07/07/linuxxia-cyu-yan-wei-sui-ji-shu-bian-cheng/

https://zh.wikipedia.org/wiki/%E4%BC%AA%E9%9A%8F%E6%9C%BA%E6%80%A7

https://blog.csdn.net/duyiwuer2009/article/details/49497199

http://www.cplusplus.com/reference/cstdlib/srand/?kw=srand

http://blog.jobbole.com/108049/

相關文章