【问题标题】:Why is the first result of rand() / double(RAND_MAX) is not random为什么 rand() / double(RAND_MAX) 的第一个结果不是随机的
【发布时间】:2013-07-11 16:18:33
【问题描述】:

这与这个问题有关 - random number generation in C++ ... first number not very random

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;

int main()
{
srand((unsigned int)time(NULL));

cout << rand() / double(RAND_MAX) << endl;
cout << rand() / double(RAND_MAX) << endl;
cout << rand() / double(RAND_MAX) << endl;
cout << rand() / double(RAND_MAX) << endl;
cout << rand() / double(RAND_MAX) << endl;

return 0;
}

如果您一遍又一遍地运行二进制文件 (.exe),您会注意到第一个结果始终具有相同的前三个数字。例如。每次运行总是 0.54xxxx。

不,这不是因为我发现了不存在的模式。每次运行之间等待几秒钟也无济于事。

编辑:只有第一个结果具有前三个相同的数字。其余的是“随机查找”。此外,生成器以 srand() 为种子(在上面代码示例的第一行)。

【问题讨论】:

  • 你用的是什么编译器?
  • GNU GCC 编译器(在代码块 12.11 中)。
  • 版本?无法使用 gcc 4.6.3 重现它。我在 MS vc 上看到过类似的东西,从来没有在 gcc 上看到过。请参阅:stackoverflow.com/questions/17385541/c-predictable-rand-output
  • @simonc - 前三个数字对于每次运行的第一个结果都是相同的。例如0.54xxxx.
  • @KarolyHorvath - 版本 4.7.1

标签: c++ random


【解决方案1】:

标准未指定rand 的随机性。最多 生成器将使用种子来初始化静态变量, 并从中计算下一个值,以一种应该的方式 “出现”随机(但当然是完全确定的)。 我的猜测是您机器上的实现返回 静态变量的旧值,它等于种子 第一次通过。 (这让我吃惊,这很正常 返回静态的新值。)

无论如何,这是实施质量的问题。 (我在 VC++11 中看到了同样的情况,但在 g++ 中没有。)

编辑:

只是一个快速测试,看看种子的变化如何影响第一个 返回数量:

for ( int i = 1; i <= 10; ++ i ) {
    std::srand( i );
    std::cout << i << ": " << std::rand() << std::endl;
}

VC++11 的输出:

1: 41
2: 45
3: 48
4: 51
5: 54
6: 58
7: 61
8: 64
9: 68
10: 71

使用 g++ 4.7.2(CygWin 版本):

1: 1481765933
2: 816048218
3: 150330503
4: 1632096437
5: 966378722
6: 300661007
7: 1782426941
8: 1116709226
9: 450991511
10: 1932757444

您说您在代码块下使用 g++ 看到了这一点: 我只能猜测代码块设置了一些东西,所以 g++ 使用 Microsoft 库,而不是 GNU 库 (通常是更好的解决方案)。

无论如何,解决方法很简单:替换你现在的单行 用于为生成器播种:

std::srand( std::time( NULL ) );
std::rand();        // throw out first value...

如果您需要相对较好的随机数,请放弃std::rand 完全赞成一些更严格定义的 C++11 中的生成器。 (如果你不是,你可以从 Boost 获得它们 使用 C++11。)

【讨论】:

  • @alexbuisson 这取决于你在做什么。对于简单的游戏,它可能已经足够好了,特别是如果你跳过前几个值。一些早期版本在偶数和奇数之间交替。这意味着对rand() % 6 + 1 的两次调用以模拟掷两个骰子永远不会出现6 或8。我认为今天并没有那么糟糕。当然,如果您确实需要相当好的质量:这就是 C++11 添加新的、更严格指定的生成器的原因。
  • 感谢您的回答和冗长的解释。 +1 并被接受。
  • 我尝试了你的测试,得到的输出与你在 VC++11 中得到的完全相同!
  • @Legendre 好吧,这是一个库问题,而不是编译器。我的 g++ 是 CygWin 版本(在 Windows 下——在家里,我运行 Linux),知道 CygWin,它可能使用标准库的 GNU 版本。我的猜测是 Code Blocks 设置了一些东西,以便 g++ 使用一些 Windows 标准库(尽管我不认为有与 Windows 捆绑的 libc.so 等效)。
  • 感谢您帮助我了解这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
  • 2019-04-02
相关资源
最近更新 更多