C/C++隨機數生成 rand() srand()


隨機數包括偽隨機數和物理隨機數,我要說的是使用rand()和srand()生成偽隨機數,盡管是偽隨機,也能滿足大部分要求。

 

#include <stdlib.h>

int rand(void);
返回一個偽隨機數,范圍是0-RAND_MAX(盡管實現不同,但至少是32767)

void srand(unsigned int seed);
設置偽隨機數算法的種子

 

了解隨機數的生成,需要從它內部工作原理說起。調用rand()返回的隨機數實際上是由一個算法生成的,此算法會生成一個無關聯的數字序列,它需要一個種子,根據種子生成相應的數字序列,即種子不同,生成的數字序列也不同。srand()就是用來設置算法種子的。

換一種說法,在你設置種子之時,隨機數算法就把數字隊列安排好了,每次調用rand(),就好比從序列中pop一個數出來。

如果在調用rand()之前未設置種子,種子默認值是1,建議設置種子,相對安全

 

寫了一個demo看看這兩個函數的用法:

test1未設置種子,默認值是1
test2設置種子值為2
test3使用時間設置種子

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


int main() {
    printf("test1: ");
    for (int i = 0; i < 10; ++i) {
        printf("%10d ", rand());
    }   
    printf("\n");

    printf("test2: ");
    srand(2);
    for (int i = 0; i < 10; ++i) {
        printf("%10d ", rand());
    }   
    printf("\n");

    printf("test3: ");
    struct timeval tv; 
    gettimeofday(&tv, NULL);
    srand(tv.tv_sec + tv.tv_usec);
    for (int i = 0; i < 10; ++i) {
        printf("%10d ", rand());
    }   
    printf("\n");
    return 0;
}

 

連續運行幾次的結果如下:

# ./test 
test1: 1804289383  846930886 1681692777 1714636915 1957747793  424238335  719885386 1649760492  596516649 1189641421 
test2: 1505335290 1738766719  190686788  260874575  747983061  906156498 1502820864  142559277 1261608745 1380759627 
test3: 1294573710 1359064005 1136018278  345608164 1963479234  965970445 1138858783  647030683 1547009306 2018312512 
# ./test 
test1: 1804289383  846930886 1681692777 1714636915 1957747793  424238335  719885386 1649760492  596516649 1189641421 
test2: 1505335290 1738766719  190686788  260874575  747983061  906156498 1502820864  142559277 1261608745 1380759627 
test3: 1363208023 1758248775 1516950100 1372540572  324153599 1376932489  538519276  357621213  736010851 2085413972 
# ./test 
test1: 1804289383  846930886 1681692777 1714636915 1957747793  424238335  719885386 1649760492  596516649 1189641421 
test2: 1505335290 1738766719  190686788  260874575  747983061  906156498 1502820864  142559277 1261608745 1380759627 
test3:  502196104  670340090 1579443138 1827056995 1871508517 1380041528  259014547 1145964334 1044434661 2069585472

可以發現,幾次運行結果之間,對應的前兩個數字序列是相同的,這是因為使用了相同的種子,而test3每次使用不同的種子,其生成的數字序列也不同。

所以想要使得偽隨機數更像物理隨機數,設置不同的種子是個好辦法,常見的一種方式是使用當前時間,srand(time(NULL))

 

假如有這樣一個需求,在較短時間內生成多個隨機字符串,那么我更推薦你使用gettimeofday()獲取時間,然后將tv_sec和tv_usec相加作為種子,tv_usec是微妙級別,保證毫秒級的不同時間是無壓力的

//random char
void random_chars(char *buf, uint32_t len) {
    if (!buf || len == 0) {
        return;
    }   
    struct timeval tv; 
    gettimeofday(&tv, NULL);
    srand(tv.tv_sec + tv.tv_usec);
    char src[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    uint32_t cnt = 36; 
    for (int32_t i = 0; i < len; ++i) {
        buf[i] = src[rand() % 36];
    }   
}

 

 

 

 

 


免責聲明!

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



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