编程珍珠第12章的第一个问题是:
C库rand()函数通常返回大约15个随机位。使用该函数实现函数bigrand()以返回至少30个随机位...
这是作者给出的解决方案:
int bigrand()
{
return RAND_MAX*rand() + rand(); // why add the rand() in the last
}
为什么作者在乘法后添加对rand
的调用?
答案 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);
}