一次生成随机数引发的思考

问题描述和解决

问题描述:在学习一致性hash的时候遇到的一个问题,当我使用随机字符串测试的时候,造成了雪崩效应(所有的数据都打到一个机器上)。
bug定位:首先我排除了hash函数(没有哈希冲突),最终将问题定位在随机字符串生成上。我的随机字符串生成的代码是下面这样的。随机字符串生成的逻辑很简单,在结果字符串的位置 i 上,从备选字符中随机挑选一个字符作为当前位置的元素。但是问题出现在每次生成随机字符串都要重置种子上,这样会导致一个问题:在超短的时间内生成的字符串是一样的。

std::string getRandStr(const int& len){
    static std::string bkStr = "0123456789qwertyuiopasdfghjklzxcvbnm";
    std::string randStr(len, ' ');
    srand((unsigned int)(time(NULL)));
    for(int i = 0; i < len; i++){
        randStr[i] = bkStr[rand() % bkStr.size()];
    }
    std::cout << randStr << endl;
    return randStr;
}

解决办法也很简单,只需要把重置随机数种子的语句删除掉即可

进一步的思考:随机数是如何生成的

显然,问题不能停留在解决问题的表面,应该更深一层次的思考这种现象出现的原因。这需要进一步去认识到随机数是如何生成的,下面就介绍一下随机数生成机制。

前言:我们所有的随机数生成都是伪随机数。为什么叫伪随机数呢,肯定因为他不是真正的随机数,真正的随机数不依赖任何条件,是完全随机的。我们目前生成随机的方式大都是线性同余的变种。

产生随机数的原理是: y = (a * x + b ) % m,其中a, b, n 都是常数,a 和 n 是很大的素数, 每次的x都是上一次的y,最初的x被称为种子,一般种子确定为计算机当前的时间。下面是rand和srand的源码

unsigned  long  int  next = 1;
/* rand:  return pseudo-random integer on 0..32767 */
int  rand ( void )
{
     next = next * 1103515245 + 12345;
     return  (unsigned  int )(next / 65536) % 32768;
}
/* srand:  set seed for rand() */
void  srand (unsigned  int  seed)
{
     next = seed;
}

从源码中可以看出来,使用一个数字作为随机数种子,那么之后出现的随机数都是固定的。因此最初问题的根源在于使用了相同的数字初始化随机数种子,导致了每次生成的随机数都是一样的。这给我一个经验:要想在短时间内得到大量的随机字符串,不要重复初始化我们的的随机数种子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值