生成0到n范围内的随机数,其中n可以> RAND_MAX

如何在0到n的范围内生成一个随机数,其中n可以在c,c ++中> RAND_MAX?

谢谢。

将生成分为两个阶段,然后合并生成的数字。

随机数是一个非常专业的主题,除非你是一个数学junky很容易出错。 因此,我建议不要从多个来源构建一个随机数,你应该使用一个好的库。

我先来看看boost :: Random

如果这不是足够的尝试这个组sci.crypt.random-numbers问他们应该能够帮助的问题。

假设您要生成64位随机数,您可以这样做:

uint64_t n = 0; for(int i = 0; i < 8; ++i) { uint64_t x = generate_8bit_random_num(); n = (n << (8 * i)) | x; } 

当然,你也可以一次做16/32位,但这说明了这个概念。

如何生成8/16/32位随机数取决于您。 它可以像rand() & 0xff一样简单,也可以更好,这取决于你对随机性的关注程度。

假设使用C ++,您是否尝试过查看一个像Boost.Random这样的随机数字库。 否则,您可能需要组合多个随机数。

如果您正在寻找统一分布(或任何分配方式),您必须注意输出的统计属性足以满足您的需求。 如果您不能直接使用随机数生成器的输出,则应该非常小心地尝试组合数字以满足您的需求。

至少应该确保分发是合适的。 如果您正在寻找从0到M的整数均匀分布,并且您有一些统一的随机数生成器g()来生成小于M的输出,请确保您执行以下操作之一:

  • 将g()的k个输出加在一起,直到它们足够大( 结果不均匀
  • 取r = g()+(g()<< 16),然后计算r%M( 如果r的范围不是M的偶数倍,它将对该范围内的某些值进行加权,比其他值略大; -left本身是有问题的,除非g()输出介于0和2的幂减1之间的范围

除此之外,序列的术语之间存在互相关的可能性(随机数发生器应该产生独立的相同分布的输出)。

阅读计算机编程艺术卷。 2(Knuth)和/或Numerical Recipes并提出问题直到你有信心。

如果您的实现具有足够大的整数类型来保存您需要的结果,那么通过简单地使用生成所需范围的生成器而不是尝试组合较小生成器的输出,通常更容易获得合适的分布。

当然,在大多数情况下,您只需下载Mersenne Twister或(如果您需要加密质量生成器)Blum-Blum-Shub等代码,而忘记编写自己的代码。

做x个随机数(从0到RAND_MAX)并将它们加在一起,其中

x = n%RAND_MAX

考虑一个随机变量,它可以取值{0, 1}P(0) = P(1) = 0.5 。 如果要通过对两个独立绘制求和来生成02之间的随机值,则将得到P(0) = 0.25P(1) = 0.5P(2) = 0.25

因此,除非您根本不关心RNG的PDF,否则请使用适当的库。

另见数字配方中的第7章。 (这是旧版本的链接,但这是我学习的那个;-)

有很多方法可以做到这一点。

如果你没有更好的粒度(更高的欺骗机会),那么像(在伪代码中) rand() * n / RAND_MAX可以在更大的范围内传播这些值。 问题在于,在实际代码中,您需要避免溢出,通过将rand()或n转换为足够大的类型(例如,如果RAND_MAX为0xFFFFFFFF,则为64位int)来保持乘法结果而不溢出,或者使用乘法 – 然后除法API(如GNU的MulDiv64或Win32的MulDiv ),该API针对此方案进行了优化。

如果你希望粒度下降到每个整数,你可以多次调用rand()并附加结果。 另一个答案建议根据RAND_MAX的大小为每个8位/ 16位/ 32位块调用rand()。

但是,恕我直言,上述想法可能会迅速变得复杂,不准确或两者兼而有之。 生成随机数是其他库中解决的问题,借用现有代码(例如来自Boost )可能比尝试自己编写代码要容易得多。 C ++中的开源随机数生成算法? 如果你想要除了Boost以外的东西,你会得到更多链接。

[编辑:在忙碌的一天之后进行修改…意味着今天早上回来清理我的快速回答,但是被拉开了,现在才回来。 :-)]