如何缩小rand()的数字?

时间:2010-11-16 15:46:36

标签: c++ random generator mersenne-twister

以下代码每秒输出一个随机数:

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范围内?

9 个答案:

答案 0 :(得分:76)

如果您正在使用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;

答案 1 :(得分:30)

到目前为止发布的所有示例实际上都给出了分布不均的结果。经常执行代码并创建统计信息以查看值如何变得偏斜。

在任何范围[0, N ]中生成真实统一随机数分布的更好方法如下(假设rand实际上遵循均匀分布,这是非常明显的):

unsigned result;
do {
    result = rand();
} while (result > N);

当然,这种方法很慢,但 会产生良好的分布。一种稍微聪明的方法是找到小于RAND_MAX N 的最大倍数,并将其用作上限。之后,可以安全地使用result % (N + 1)

为解释为什么天真模数方法不好以及为什么上述情况更好,请参阅Julienne关于using rand 的优秀文章。

答案 2 :(得分:26)

<击>

<击>
int rawRand = rand() % 101;

见(更多细节):

rand - C++ Reference

其他人也指出,这不会给你最好的随机数分布。如果您的代码中的这类内容很重要,则必须执行以下操作:

int rawRand = (rand() * 1.0 / RAND_MAX) * 100;

<击>

修改

三年过去了,我正在编辑。正如其他人所提到的,rand()存在很多问题。显然,当有更好的替代方案时,我不能推荐它的使用。您可以在此处阅读有关详细信息和建议的所有信息:

rand() Considered Harmful | GoingNative 2013

答案 3 :(得分:4)

请参阅man 3 rand - 您需要通过除以RAND_MAX进行缩放以获得范围[0,1],之后您可以将目标范围乘以100。

答案 4 :(得分:4)

你可以做到

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位整数并使用100个数字作为输出时,数字0-16表示为1.00000000000000000455%的数字(相对精度相同分布为1%乘以约10 -18 ),而数字17-99用数字表示0.99999999999999999913%。是的,不是完美分布的,而是对小跨度的非常好的近似。

另请注意,OP在哪里要求分配相同的号码?对于我们所知道的所有这些都被用于小偏差无关紧要的目的(例如,加密以外的任何东西 - 如果他们使用加密数字这个问题对于他们编写自己的密码学来说太天真了)。

编辑 - 对于真正关心随机数均匀分布的人,以下代码可行。请注意,这不一定是64位随机整数的最佳选择,每10 ^ 18次调用需要两次rand()次调用。

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;

答案 5 :(得分:0)

对于范围最小值到最大值(包括),请使用:int result = rand() % (max - min + 1) + min;

答案 6 :(得分:-4)

你想要一个答案多长时间。

最简单的是使用除以101时的余数进行转换:

int value = rawRand % 101;

半熟练者会使用双打重新缩放:

double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5);   // round up for above 0.5

纯粹主义者会说rand不会产生随机数。

对于您的信息,随机数的质量是通过采用一系列数字然后计算该序列的来源是随机的数学概率来衡量的。如果你是随机性的话,使用余数的简单hack是一个非常糟糕的选择。

答案 7 :(得分:-4)

有些人发布了以下代码作为示例:

int rawRand = (rand() / RAND_MAX) * 100;

这是解决问题的无效方法,因为rand()和RAND_MAX都是整数。在C ++中,这会导致积分除法,这将截断结果小数点。当RAND_MAX&gt; = rand()时,该操作的结果是1或0,这意味着rawRand只能是0或100.正确的方法是:

int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;

由于一个操作数现在是一个双精度浮点除法,它将返回0到1之间的正确值。

答案 8 :(得分:-5)

rawRand%101会给出[0-100],包括。