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

时间:2009-10-06 17:55:20

标签: c++ c

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

感谢。

9 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:5)

随机数是一门非常专业的主题,除非你是数学杂耍,否则很容易出错。所以我建议不要从多个来源构建一个随机数,你应该使用一个好的库。

我先看看boost::Random

如果这不是一个有效的尝试这个小组sci.crypt.random-numbers 在那里提出问题,他们应该能够提供帮助。

答案 2 :(得分:3)

假设你想生成一个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一样简单,也可以更好,这取决于你对随机性的关注程度。

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

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

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

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

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

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

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

x = n%RAND_MAX

答案 7 :(得分:0)

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

如果你没有更低的粒度(更高的欺骗机会),那么(在伪代码中)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)可能要比尝试自己编写代码容易得多。如果您想要除Boost之外的其他内容,Open source random number generation algorithm in C++?会有更多链接的答案。

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

答案 8 :(得分:0)

考虑一个随机变量,它可以使用{0, 1}取值P(0) = P(1) = 0.5。如果您想通过对两个独立绘图进行求和来生成02之间的随机值,您将拥有P(0) = 0.25P(1) = 0.5P(2) = 0.25

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

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