【发布时间】:2013-11-03 22:00:23
【问题描述】:
最好的方法是什么?我的编译器显示 RAND_MAX = 32,767。所以我很好奇如何获得 0 到 100,000 之间的统一随机生成值?
【问题讨论】:
-
使用
<random>标头。
最好的方法是什么?我的编译器显示 RAND_MAX = 32,767。所以我很好奇如何获得 0 到 100,000 之间的统一随机生成值?
【问题讨论】:
<random> 标头。
我将把 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;
【讨论】:
& 131071,并拒绝任何大于 100,000 的值。请注意,这具有不确定的运行时间,但这是获得无偏分布的唯一直接方法。不要使用模运算符。
& 131071 当然是伪装的模运算符% 131072,所以说永远不要使用模运算符有点虚伪。每当(rand_max + 1) mod n > 0 时,模数(以任何形式)都会有偏差。
RAND_MAX 中有 15 位并试图神奇地从中提取 17 位是行不通的(如果你想这样称呼它,那就是“偏见”,但这就是为什么我说需要结合两个随机数,例如rand()|(rand()<<15) 之类的东西来拥有足够的随机位。无论您是否移动它们,随机位都是同样随机的,并且 ...
(8+1) modulo 2 > 0 但(8+1) modulo 3 = 0.
你应该下载并使用一个严肃的 PRNG,比如 Gnu Scientific Library 中提供的那些。
【讨论】:
我很久以前在某个网站上发现了以下功能。作者声称函数提供了良好的一致性。
#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 并合并输出,否则您的分配中将存在“漏洞”。
double 值,在 0 和 100000.0 之间有更多 double 值。 (在数学上,两组大小相等)。根据鸽巢原理,一定有洞。也就是说,double 通常在 0 和 1 之间具有大约 2^62 个值的 IIRC。(一半的数字是正的,一半的正值介于 1 和无穷大之间)。显然,您需要 5 次调用 rand() 才能获得超过 60 位,以避免出现漏洞。
我发现首先是#include <time.h>,然后您可以写srand(time(NULL)); 将值植入随机函数。那么你所要做的就是使用这条线:(rand() % 99999 + 1);。这应该会给你一个介于 0 到 100,000 之间的随机值。如果需要,您也可以将其分配给变量:int myVar = (rand() % 99999 + 1);。希望有帮助! (而且我希望我是完全正确的。我仍在获得 CS 学位并仍在学习 C++,但我之前已经这样做了,并且成功了。)
【讨论】:
这是您的代码:
100000.0f * ((float)rand() / 32767.0f)
这将产生从 0 到 100000 的随机浮点数,但您可以在此处使用 100000 以外的任何正数。
更新:
确实(感谢下面 psj 的评论)我已经意识到上面覆盖了大约 0..100000 范围的 1/3。
【讨论】: