【问题标题】:Why is <random> library producing the same results every time when using std::uniform_int_distribution为什么每次使用 std::uniform_int_distribution 时 <random> 库都会产生相同的结果
【发布时间】:2026-01-16 17:40:01
【问题描述】:

注意事项:

  1. 我的编译器是 g++ 5.1.0-2 和 c++14 语言标准
  2. 我的 IDE 是 Code::Blocks(我也在 Dev-C++ 上尝试过代码)
  3. 我测试代码的在线 IDE 是 http://cpp.sh/ (C++ shell) 和 https://www.codechef.com/ide (CodeChef.com 的 IDE) 都运行 c++14
  4. 使用在线 IDE 时代码运行正常,这让我更加困惑。

代码如下:

#include <iostream>
#include <random>
#include <cstdlib>
#include <ctime>
#include <chrono>

int main() {
    srand(time(0));
    long long seed = rand();
    std::default_random_engine rand_num(seed);
    std::uniform_int_distribution<long long> range(0, 10);
    long long a = range(rand_num);
    long long b = rand_num();
    std::cout<<seed<<"\n"; // the seed is different every time (tested)
    std::cout<<a<<"\n";
    std::cout<<b<<"\n";
    system("pause");
    return 0;
}

在我自己的计算机上运行代码时,带有 std::uniform_int_distribution (a) 的那个不是随机的,但可以正常工作并在在线 IDE 上创建一个随机数。

没有 std::uniform_int_distribution (b) 的那个在在线 IDE 和我自己的电脑上都可以正常工作。

有什么问题?我该如何解决?

更新:代码在 mt19937 引擎(std::mt19937 和 std::mt19937_64)上运行正常

【问题讨论】:

  • 您是否尝试打印seed 和调用time(0) 的结果,以查看非随机性的来源?
  • @Pixelchemist 是的,种子每次都不一样。 (将信息添加到问题中)
  • 好的,您是否在打印整个序列时测试了多次运行? (for(unisgned i=0; i&lt;10; ++i) { std::cout &lt;&lt; range(rand_num) &lt;&lt; ' '; })
  • @Pixelchemist 是的。事实上,我在使用 for 循环创建随机数组时发现了这个问题。
  • 我用 gcc 4.8/c++11 对其进行了测试,它按预期工作。看起来像是特定 stl 版本的实现中的错误。你能更精确地指定 gcc 版本吗? gcc.gnu.org 上不存在版本号 5.10-2。

标签: c++ c++11 random compiler-errors


【解决方案1】:

这似乎是 Windows 上 g++ 实现的一个已知问题。查看已接受的类似问题的答案:Why do I get the same sequence for every run with std::random_device with mingw gcc4.8.1?

为避免该问题,您可以使用&lt;chrono&gt; 设施来播种随机数生成器:

#include <iostream>
#include <random>
#include <cstdlib>
#include <ctime>
#include <chrono>

int main() {
    srand(time(0));
    long long seed = rand();

    std::default_random_engine rand_num{static_cast<long unsigned int>(std::chrono::high_resolution_clock::now().time_since_epoch().count())};
    //                                  ^ ^ ^ ^ ^ ^^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
    std::uniform_int_distribution<long long> range{1,10};

    long long a = range(rand_num);
    long long b = rand_num();
    std::cout<<seed<<"\n"; // the seed is different every time (tested)
    std::cout<<a<<"\n";
    std::cout<<b<<"\n";
    system("pause");
    return 0;
}

这在每次运行时都给了我不同的结果(在 Windows 上使用 g++)。

【讨论】:

  • 正如我在更新中提到的,它适用于 mt19937 引擎
  • @SalehShamloo 抱歉,我已使用 std::default_random_engine 更新了答案。它在我的环境中有效。
  • 它有效。谢谢你。但是当我把它放在for 循环中时,我得到了相同的结果。它们在每次运行中都不同,但与 for 循环中生成的其他数字没有区别。
  • 什么意思? for ( int i=0; i&lt;16; i++) { std::cout &lt;&lt; range(rand_num) &lt;&lt; '\n'; } 对我来说很好......
  • 对不起,我的错。无论如何,谢谢你的回答。这很有帮助。
【解决方案2】:

您的代码在 Visual C++ 中运行良好,但在 g++ 5.2.0 中对我来说却失败了。在我看来,它就像 gcc 标准库中的一个错误。

还有更多的证据表明使用default_random_engine 通常只是一个坏主意,并且使用time(0) 作为种子也非常糟糕(尽管快速检查表明将其更改为使用random_device 作为种子仍然会产生损坏的结果)。

【讨论】:

  • random_device 实际上每次运行都会为我生成相同的种子。我正在使用 Mingw-W64(gcc 4.9.1)
  • 我认为它在5.1.0-25.2.0 中不起作用但在[ideone(使用__VERSION__ == 5.1.1 20150711)] 之间不起作用。
  • @Pixelchemist:这是一个库问题,所以问题是编译器在线使用的 library 是什么。如果他们使用libc++(作为明显的替代方案),那可以解释很多。哦,但是random_device 不应该每次都给出相同的结果——你确定你正确地调用了它吗?它是一个类,所以要在不定义对象的情况下调用它,你需要使用random_device()()
  • random_device 在 MinGW 中总是给出相同的序列,或者至少是这样:*.com/q/18880654/10077
  • 是的。这是一个错误。它已在 5.3 版中修复
最近更新 更多