【问题标题】:C++ generate a random number between 0 and 100,000C++ 生成 0 到 100,000 之间的随机数
【发布时间】:2013-11-03 22:00:23
【问题描述】:

最好的方法是什么?我的编译器显示 RAND_MAX = 32,767。所以我很好奇如何获得 0 到 100,000 之间的统一随机生成值?

【问题讨论】:

标签: c++ random g++ solaris


【解决方案1】:

我将把 juanchopanza 的评论作为答案。

如果您的编译器提供 <random> 标头 (C++11),请使用它。

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 10000);

std::cout << dis(gen) << std::endl;

【讨论】:

  • 如果由于某种原因您不能或不想这样做,请使用具有足够位的生成器(或将 2 个调用与 shift 和 or 结合起来),将其屏蔽为下一个最接近的 2 次幂(在您的情况下&amp; 131071,并拒绝任何大于 100,000 的值。请注意,这具有不确定的运行时间,但这是获得无偏分布的唯一直接方法。不要使用模运算符。
  • @Damon: &amp; 131071 当然是伪装的模运算符% 131072,所以说永远不要使用模运算符有点虚伪。每当(rand_max + 1) mod n &gt; 0 时,模数(以任何形式)都会有偏差。
  • @MSalters:虽然在这种情况下,伪装的模运算符真的不是模运算符。屏蔽无偏数的最低 N 位不会以任何方式偏向这些位。这确实是一个重要的区别。当然,在RAND_MAX 中有 15 位并试图神奇地从中提取 17 位是行不通的(如果你想这样称呼它,那就是“偏见”,但这就是为什么我说需要结合两个随机数,例如rand()|(rand()&lt;&lt;15) 之类的东西来拥有足够的随机位。无论您是否移动它们,随机位都是同样随机的,并且 ...
  • ...无论您切掉底部的 5 位、10 位还是 17 位,它们都是同样随机的(嗯,伪随机)。如果不是,则随机数生成器已损坏。另一方面,模(不是 2 的幂)增加了偏差,因为它使数字环绕。即使这些位之前是(伪)随机的,它们也不会是之后的。好吧,它们仍然是“随机的”,但有些出现的频率是其他的两倍。
  • @Damon:屏蔽掉无偏数字的低位肯定会产生偏差。简单地说,给定 [0,2] 范围内的无偏数,屏蔽低位将以 2/3 的概率给出 0。给定 [0,8] 范围内的数字,模 2 将再次产生偏差(0 有 5/9 的机会),但模 3 不会(所有结果都有 1/3 的机会)。为什么? (8+1) modulo 2 &gt; 0 但(8+1) modulo 3 = 0.
【解决方案2】:

你应该下载并使用一个严肃的 PRNG,比如 Gnu Scientific Library 中提供的那些。

【讨论】:

  • 我们已经有了标准的严重 PRNG(Boost 也有一些)。
  • @chris 最近的 C++ 标准,是的。他的编译器,不一定。
  • 嗯,这就是 Boost 的真正用途。您几乎可以假设每个 C++ 开发人员都拥有它。
  • @chris 所以我们都说他可能会从使用正确完成工作的外部库中受益。他有选择是一件好事。
  • 不能使用外部库。这是一个学校项目,如果教授。他的系统上没有。我不能把它放在我的身上。我以前从来不需要大于 10,000 的随机数
【解决方案3】:

我很久以前在某个网站上发现了以下功能。作者声称函数提供了良好的一致性。

#define RS_SCALE (1.0 / (1.0 + RAND_MAX))
double drand(void) 
{
    double d;
    do {
       d = (((rand () * RS_SCALE) + rand ()) * RS_SCALE + rand ()) * RS_SCALE;
    } while (d >= 1); /* Round off */
    return(d);
}

正如下面的评论中所指出的,这给出了 0..1 范围内的答案,所以你必须乘以 100000,即drand()*100000。

【讨论】:

  • 这会返回 [0, 1) 未能回答问题。
  • 应该注意rand(RAND_MAX 为 32k)中没有足够的位来处理这种事情。除非您执行一些技巧,例如两次调用 rand 并合并输出,否则您的分配中将存在“漏洞”。
  • @Damon 我不明白为什么由于 RAND_MAX=32k 会出现孔。如果给出 drand() 的分布在 [0,1) 范围内是均匀的(并且在此范围内没有孔),那么它与 100000 的缩放比例在 [0,100000)范围内也将是均匀的并且没有孔,将不是吗?
  • @IgorPopov:不,FP 数学不遵循真实数学的规则。在 0 和 1.0 之间有有限数量的 double 值,在 0 和 100000.0 之间有更多 double 值。 (在数学上,两组大小相等)。根据鸽巢原理,一定有洞。也就是说,double 通常在 0 和 1 之间具有大约 2^62 个值的 IIRC。(一半的数字是正的,一半的正值介于 1 和无穷大之间)。显然,您需要 5 次调用 rand() 才能获得超过 60 位,以避免出现漏洞。
【解决方案4】:

我发现首先是#include &lt;time.h&gt;,然后您可以写srand(time(NULL)); 将值植入随机函数。那么你所要做的就是使用这条线:(rand() % 99999 + 1);。这应该会给你一个介于 0 到 100,000 之间的随机值。如果需要,您也可以将其分配给变量:int myVar = (rand() % 99999 + 1);。希望有帮助! (而且我希望我是完全正确的。我仍在获得 CS 学位并仍在学习 C++,但我之前已经这样做了,并且成功了。)

【讨论】:

  • rand() 将返回的最大值是 RAND_MAX,通常为 32,767。
【解决方案5】:

这是您的代码:

100000.0f * ((float)rand() / 32767.0f)

这将产生从 0 到 100000 的随机浮点数,但您可以在此处使用 100000 以外的任何正数。

更新:

确实(感谢下面 psj 的评论)我已经意识到上面覆盖了大约 0..100000 范围的 1/3。

【讨论】:

  • 一致性取决于 rand() 这里所以我也不确定 ;-)
  • @MihaiMaruseac 我确定不是。它只能产生[0,100000]范围内大约三分之一的整数。
  • 所做的只是缩放一个数字随机数,您将错过大部分范围。
猜你喜欢
  • 2014-04-11
  • 2011-08-10
  • 2011-04-29
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
相关资源
最近更新 更多