如何从Rand()中缩小数字?
-
11-10-2019 - |
题
以下代码每秒输出一个随机数:
int main ()
{
srand(time(NULL)); // Seeds number generator with execution time.
while (true)
{
int rawRand = rand();
std::cout << rawRand << std::endl;
sleep(1);
}
}
我如何减少这些数字,以便它们总是在0-100的范围内?
解决方案
如果您使用的是C ++,并且担心良好的分发,则可以使用 TR1 C ++ 11 <random>
.
#include <random>
std::random_device rseed;
std::mt19937 rgen(rseed()); // mersenne_twister
std::uniform_int_distribution<int> idist(0,100); // [0,100]
std::cout << idist(rgen) << std::endl;
其他提示
到目前为止发布的所有示例实际上给出了分布不佳的结果。经常执行代码并创建统计量,以查看值如何偏斜。
产生真实的更好方法 制服 随机数分布在任何范围内[0, n]是以下内容(假设 rand
实际上遵循统一的分布,这远非显而易见):
unsigned result;
do {
result = rand();
} while (result > N);
当然,这种方法很慢,但是 做 产生良好的分布。这样做的一种稍聪明的方法是找到 n 比小于 RAND_MAX
并将其用作上限。之后,可以安全地接受 result % (N + 1)
.
用于解释 为什么 幼稚的模量法是不好的,为什么上述更好, 请参阅朱利安(Julienne)的出色文章 使用 rand
.
int rawRand = rand() % 101;
请参阅(有关更多详细信息):
其他人还指出,这不会为您提供最佳的随机数分布。如果这种事情在您的代码中很重要,则必须这样做:
int rawRand = (rand() * 1.0 / RAND_MAX) * 100;
编辑
三年过去了,我正在编辑。正如其他人提到的 rand()
有很多问题。显然,当有更好的替代方案前进时,我不建议它使用它。您可以在此处阅读有关详细信息和建议的所有信息:
你可以做
cout << rawRand % 100 << endl; // Outputs between 0 and 99
cout << rawRand % 101 << endl; // outputs between 0 and 100
对于人民降价;注意最初发布后一分钟,我留下了评论:
从 http://www.cplusplus.com/reference/clibrary/cstdlib/rand “请注意,尽管此模型操作不会在跨越中产生真正均匀分布的随机数(因为在大多数情况下,较低的数字可能稍微稍微稍微降低),但对于短跨度来说,这通常是一个很好的近似值。”
具有64位INT并使用100个数字作为输出,数字0-16代表了数字的1.000000000000000455%-18),而数字为17-99的代表为0.99999999999999999913%。是的,不是完美的分布,而是小跨度非常好的近似值。
另请注意,OP在哪里要求分布相同的数字?就我们所知)。
编辑 - 对于真正关注随机数均匀分布的人,以下代码作用。请注意,这不一定像64位随机INT一样最佳,它将需要两个调用 rand()
一次每10^18呼叫。
unsigned N = 100; // want numbers 0-99
unsigned long randTruncation = (RAND_MAX / N) * N;
// include every number the N times by ensuring rawRand is between 0 and randTruncation - 1 or regenerate.
unsigned long rawRand = rand();
while (rawRand >= randTruncation) {
rawRand = rand();
// with 64-bit int and range of 0-99 will need to generate two random numbers
// about 1 in every (2^63)/16 ~ 10^18 times (1 million million times)
// with 32-bit int and range of 0-99 will need to generate two random numbers
// once every 46 million times.
}
cout << rawRand % N << stdl::endl;
看 man 3 rand
- 您需要通过分裂来扩展 RAND_MAX
要获得范围[0,1],然后您可以为目标范围乘以100。
对于最大范围的最小值(包含),请使用: int result = rand() % (max - min + 1) + min;
您想要多长时间的答案。
最简单的是将剩余的转换除以101:
int value = rawRand % 101;
半司师将使用双打恢复:
double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5); // round up for above 0.5
纯粹主义者会说兰德不会产生随机数。
对于您的信息,通过采取一系列数字,然后计算该序列的源是随机的数学概率来衡量随机数的质量。如果您是随机性,则使用其余部分的简单骇客是一个非常糟糕的选择。
有些人将以下代码发布为示例:
int rawRand = (rand() / RAND_MAX) * 100;
这是解决问题的一种无效方法,因为rand()和rand_max都是整数。在C ++中,这会导致整体分裂,这将截断结果小数点。作为rand_max> = rand(),该操作的结果为1或0,这意味着Rawrand只能是0或100。正确执行此操作的方法是以下内容:
int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;
由于操作数现在是双重的,因此使用了浮点划分,将返回0到1之间的适当值。
RAWRAND%101将给出[0-100],包括。