下面的代码旨在生成区间[1unix time]中五个伪随机数的列表.我在default_random_enginetime(0)之间植入种子,这将在unix time中返回系统时间.当我使用Microsoft Visual Studio 2013在Windows 7上编译并运行此程序时,它的工作原理与预期一致(见下文).然而,当我在Arch Linux中使用g++编译器时,它的行为却很奇怪.

在Linux中,每次将生成5个数字.最后4个数字在每次执行时都会不同(通常情况下也是如此),但第一个数字将保持不变.

Windows和Linux上5次执行的输出示例:

      | Windows:       | Linux:        
---------------------------------------
Run 1 | 54,01,91,73,68 | 25,38,40,42,21
Run 2 | 46,24,16,93,82 | 25,78,66,80,81
Run 3 | 86,36,33,63,05 | 25,17,93,17,40
Run 4 | 75,79,66,23,84 | 25,70,95,01,54
Run 5 | 64,36,32,44,85 | 25,09,22,38,13

更令人不解的是,在Linux上,第一个数字周期性地增加1.在获得上述输出后,我等待了大约30分钟,再次try 发现第一个数字已经改变,现在总是生成26.它继续周期性地增加1,现在是32.它似乎与不断变化的值time(0)相对应.

Why does the first number rarely change across runs, and then when it does, increment by 1?

密码.它整齐地打印出5个数字和系统时间:

#include <iostream>
#include <random>
#include <time.h>

using namespace std;

int main()
{
    const int upper_bound = 100;
    const int lower_bound = 1;

    time_t system_time = time(0);    

    default_random_engine e(system_time);
    uniform_int_distribution<int> u(lower_bound, upper_bound);

    cout << '#' << '\t' << "system time" << endl
         << "-------------------" << endl;

    for (int counter = 1; counter <= 5; counter++)
    {
        int secret = u(e);
        cout << secret << '\t' << system_time << endl;
    }   

    system("pause");
    return 0;
}

推荐答案

事情是这样的:

  • libstdc++(GCC的标准库)中的default_random_engineminstd_rand0,这是一个简单的线性同余引擎:

    typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647> minstd_rand0;
    
  • 这个引擎生成随机数的方式是xi+1=(16807xi+0)mod 2147483647.

  • 因此,如果种子数相差1,那么大多数情况下,第一个生成的数字相差16807.

  • 这个生成器的范围是[12147483646].libstdc++uniform_int_distribution将其映射为[1uniform_int_distribution]范围内的整数的方式本质上是这样的:生成一个数字n.如果数字不大于2147483600,则返回(n - 1) / 21474836 + 1;否则,请使用新号码重试.

    很容易看出,在绝大多数情况下,两个仅相差16807的n将在[1n]中产生相同的数字.事实上,我们预计生成的数字大约每21474836/16807=1278秒或21.3分钟增加一个,这与您的观察结果非常吻合.

MSVC的default_random_enginemt19937,没有这个问题.

Linux相关问答推荐

BASH-SCRIPT-在特定行合并两个文件

无法分析nasm中的单词

awk 打印除最后一列以外的所有内容 + 最后一列

未找到 SDL_Vertex 和 SDL_RenderGeometry

将 Visual Studio C++ 项目迁移到 Linux 和 CMake

8 个半小时范围的 Crontab 表达式

为什么我的 Docker 进程不断在我的 Raspberry Pi 上重新启动?

使用 sed 或 awk 在 linux 中将第一行中的一个单词替换为第二行中的另一个单词

在 Windows 上通过 SSH 运行 django 应用程序

ftell 在文件描述符上?

DMA 和内存映射 IO 有什么区别?

无法创建Java虚拟机

如何在 Linux 中为 C 或 C++ 的进程设置 CPU 亲和性?

如何在非阻塞套接字上处理 OpenSSL SSL_ERROR_WANT_READ / WANT_WRITE

kdevtmpfsi 使用整个 CPU

如何在 Linux 中查找所有以 .rb 结尾的文件?

如何在没有空格的情况下打印 awk?

C++:使用 longjmp 和 setjmp 安全吗?

比较文件的日期 bash

如何在 linux 或 unix 上找到用户的主目录?