为什么rand()给我的是负数?

  • 本文关键字:rand c++ random
  • 更新时间 :
  • 英文 :


我试图使它使rand_draw保持0-8之间的随机正数。但是这段代码在一些迭代中一直给出负数。发生什么事情了?

srand(time(0));
int draw_count = 8;
int rand_draw = (2 * rand()) % draw_count;
cout << rand_draw << endl;

根据cppreference, rand():

返回一个介于0和RAND_MAX(包括0和RAND_MAX)之间的伪随机整数值。

RAND_MAX的值是实现定义的,但很可能是int中可以表示的最大值。通过加倍你从rand()得到的值,结果可能溢出到一个负数。这实际上是未定义的行为。

我认为没有理由将rand()的返回值加倍。您可以很简单地纠正这个错误:

int rand_draw = rand() % (draw_count + 1);

这将给出0到8之间的随机值,如您所指定的。

但是在现代c++中,使用c++标准库中的uniform_int_distribution是一种更好的方法。下面是链接页面中的示例,修改后显示您指定的范围:

#include <random>
#include <iostream>

int main()
{
std::random_device rd;  //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> distrib(0, 8);

for (int n=0; n<10; ++n)
//Use `distrib` to transform the random unsigned int generated by gen into an int in [0, 8]
std::cout << distrib(gen) << ' ';
std::cout << 'n';
}

rand()函数将在此范围内生成一个随机数[0,RAND_MAX]。RAND_MAX是一个很大的数字。在这个链接

中讨论了更多细节。当你使用2*rand()时,基本上是将生成的数字向左移动1位。如果生成的数字足够大,从左边开始的第二个比特是1,那么向左移动后生成的是一个负数。

下面是一个例子:假设生成的十六进制数是0x70000011。这个数字的四位最高有效位是0111,向左移动1位后,你可以看到符号位在变化。然后尝试使用%操作,结果是负数。

  1. rand() % draw_count ->生成数字[0,draw_count)
  2. (rand() % draw_count) + draw_count ->生成number [draw_count, 2* draw_count)
  3. rand() % (2draw_count) ->生成数字[0,2draw_count)

我想出了一个解决方案,因为我只能使用rand()函数。我只是在之后添加了一个if语句来检查它是否为偶数,如果是偶数,则将变量设置为rand_draw,如果不是,则增加1。

int rand_draw = rand() % draw_count;
if (rand_draw % 2 == 0)
{
rand_draw = rand_draw;
}
else
{
rand_draw += 1;
}

最新更新