C/C++随机数生成 rand() srand()

12 篇文章 0 订阅

转载自 http://www.cnblogs.com/caosiyang/archive/2012/07/03/2575236.html


随机数包括伪随机数和物理随机数,我要说的是使用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];
    }   
}
复制代码

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值