2

每当我在 C++ 中使用 rand 函数时:

#include<iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;
int main(){
srand(time(0));
int n=(rand()%6)+1;
cout<<"The dice roll is "<<n<<"."<<endl;
}

我在第 5 行收到关于从 time_t 转换为 int 的警告:

srand(time(0));

有没有办法摆脱这个警告?

4

6 回答 6

9

实际上,您应该使用带有 srand()的无符号整数:

srand((unsigned) time(0));
于 2009-05-03T21:00:58.177 回答
5

另一方面,这段代码:

rand()%6

通常被认为是一种不好的做法。rand() 的低位比高位的随机性要小得多。如果你这样做,你会得到更好的随机性:

(rand() >> 8)%6

例如。

编辑:

有关这方面的更多详细信息,请参阅此说明以及Dobbs 博士杂志的这篇文章,其中至少暗示了原因:

注意:请勿使用

  y = rand()  %  M;

因为这侧重于 rand() 的低位。对于 rand() 通常是线性同余随机数生成器,低字节的随机性远低于高字节。事实上,最低位在 0 和 1 之间循环。因此 rand() 可能在偶数和奇数之间循环(试试看)。注意 rand() 不必是线性同余随机数生成器。完全允许它是没有这个问题的更好的东西。

东道主:

最重要的一点是,通常(线性同余)随机数生成器输出的低位是最不“随机”的。也就是说,低位中的模式是常见的。因此,您讨论中例行滚动的输出并不令人惊讶。此外,依靠高位来确定返回的整数是可以避免的。

例如,如果您想选择一个随机的“真”或“假”值,并且您使用了以下代码:

rand() % 2

然后你可能最终会看到结果的模式:

1,0,1,0,1,0,1,0,1,0(等)

这显然不是那么随机,但它是可能正在使用的线性同余生成器的一个属性。一个更好的方案(对于 C++)可能是使用Boost.Random库,它支持所有类型的可插拔随机生成器(包括没有这个缺陷的 Mersenne Twister)。

于 2009-05-03T21:03:15.847 回答
2

使用显式强制转换来消除警告:

srand((int)time(0));
于 2009-05-03T20:54:12.390 回答
2

要摆脱警告,您应该使用静态强制转换为无符号整数。

srand(static_cast<unsigned int>(time(0)));

在相关说明中,rand 的结果应向右移动以消除低位中的任何偏差。

int n = ((rand() >> 8) % 6) + 1;

最后,在 C++ 中,C 时间库和标准库应包含为:

#include <ctime>
#include <cstdlib>

这会将函数放置在适当的命名空间“std”中。

于 2009-05-03T23:01:24.487 回答
1

两个旁注:

  • 在 C++ 中包含 C 头文件的标准方法是这样的:#include <cstdio>.
  • 传递给的参数time()是一个指针,很多人认为它NULL是一个比0.
于 2009-05-03T21:05:28.570 回答
0

还,

 rand() % 6

将引入一个小的偏差。由于 RAND_MAX % 6 为 1,因此零和一的出现频率将略高于二到六。在这种情况下,每 5461 次返回较高的数字,它们就会返回 5462 次,因此您可能不会注意到它。但是,如果您想要的数字范围很大,则偏差可能很大。例如,如果你这样做了rand() % 32000,那么 0 - 767 范围内的数字出现的频率将是 768 - 32000 的两倍。

于 2009-05-03T21:30:50.103 回答