为什么这段代码调用rand()两次以获得至少N个随机位?

时间:2014-05-30 03:24:13

标签: c random

编程珍珠第12章的第一个问题是:

  

C库rand()函数通常返回大约15个随机位。使用该函数实现函数bigrand()以返回至少30个随机位...

这是作者给出的解决方案:

int bigrand()
{
    return RAND_MAX*rand() + rand(); // why add the rand() in the last 
}

为什么作者在乘法后添加对rand的调用?

2 个答案:

答案 0 :(得分:2)

如果没有额外的rand(),结果将是RAND_MAX的倍数,因此甚至不会模糊随机。

事实上,您展示的代码并不完全正确,应该是

int bigrand()
{
    return (RAND_MAX+1)*rand() + rand(); // why add the rand() in the last 
}
对于某些x,

RAND_MAX几乎总是2 ^ x-1。如果没有+1 RAND_MAX*rand()rand()之间存在重叠,那么您实际上会添加两个随机数字,这会使随机性发生偏差(例如,将两个骰子组合在一起)。

添加额外的1使其为2的幂,因此RAND_MAX*rand()的底部x位全为0;额外的rand()填写底部位。这更像是将第一个rand()向左移动而在第二个中移动。或者

请注意,此方法仅适用于生成一些非关键测试数据,但如果需要真正的线性随机性,则不应使用此方法;如果需要30位,则应使用真正的30位(或更多)随机数生成器。

答案 1 :(得分:0)

解决方案的问题是:

  

C库rand()函数通常返回大约15个随机位。使用该函数实现函数bigrand()以返回至少30个随机位...

一种直接的方法是组合2 rand()个调用的输出,填充必要的位数,每次15个。此

RAND_MAX * rand()

填充最重要的15位,其余部分负责处理。

如果RAND_MAX的值使int类型溢出(在我的系统上,我找到#define RAND_MAX 0x7fffffff),这当然是未定义的行为。如果rand规范稍微严格一些,例如要说只有最低15位是随机的(一种不太可能和虚构的情况),我们可以这样做:

int bigrand(void)
{
    return ((rand() & 0x7fff) << 15) | (rand() & 0x7fff);
}