<random> 在 Linux 中生成相同的数字,但在 Windows 中不生成

2024-11-12 08:36:00
admin
原创
209
摘要:问题描述:下面的代码用于生成区间 [1,100] 内的五个伪随机数列表。我用 为该程序设定种子default_random_engine,返回unix 时间time(0)中的系统时间。当我使用 Microsoft Visual Studio 2013 在 Windows 7 上编译并运行该程序时,程序按预期运...

问题描述:

下面的代码用于生成区间 [1,100] 内的五个伪随机数列表。我用 为该程序设定种子default_random_engine,返回unix 时间time(0)中的系统时间。当我使用 Microsoft Visual Studio 2013 在 Windows 7 上编译并运行该程序时,程序按预期运行(见下文)。但是,当我使用 g++ 编译器在 Arch Linux 中执行此操作时,程序的行为很奇怪。

在 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 分钟,然后再次尝试,发现第一个数字已更改,现在始终生成为 26。它继续定期增加 1,现在为 32。它似乎与 的变化值相对应time(0)

为什么第一个数字在运行过程中很少发生变化,而当它发生变化时,却增加 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 << '#' << '    ' << "system time" << endl
         << "-------------------" << endl;

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

    system("pause");
    return 0;
}

解决方案 1:

事情是这样的:

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

typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647> minstd_rand0;
  • 该引擎生成随机数的方式是 x i+1 = (16807x i + 0) mod 2147483647。

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

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

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

MSVC 的default_random_enginemt19937,它没有这个问题。

解决方案 2:

std::default_random_engine实现定义。请使用std::mt19937std::mt19937_64代替。

此外std::time,由于ctime函数不太准确,因此请使用<chrono>标头中定义的类型代替:

#include <iostream>
#include <random>
#include <chrono>

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

    auto t = std::chrono::high_resolution_clock::now().time_since_epoch().count();

    std::mt19937 e;
    e.seed(static_cast<unsigned int>(t)); //Seed engine with timed value.
    std::uniform_int_distribution<int> u(lower_bound, upper_bound);

    std::cout << '#' << '    ' << "system time" << std::endl
    << "-------------------" << std::endl;

    for (int counter = 1; counter <= 5; counter++)
    {
        int secret = u(e);

        std::cout << secret << '    ' << t << std::endl;
    }   

    system("pause");
    return 0;
}

解决方案 3:

在 Linux 中,随机函数不是概率意义上的随机函数,而是一个伪随机数生成器。它用种子加盐,基于该种子,产生的数字是伪随机的且均匀分布。Linux 方式的优势在于,在使用来自人群的信息设计某些实验时,可以测量已知输入信息调整的实验重复性。当最终程序准备好进行实际测试时,可以通过要求用户移动鼠标、将鼠标移动与一些击键混合并添加自上次开机以来的微秒计数来创建盐(种子)。

Windows 随机数种子是从鼠标、键盘、网络和时间数字的集合中获得的。它是不可重复的。但是,如果如上所述,有人参与了实验设计,则可以将此盐值重置为已知种子。

哦,是的,Linux 有两个随机数生成器。一个默认为模 32 位,另一个为模 64 位。您的选择取决于您的测试或实际使用所需的精度需求和计算时间。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用