<随机>在Linux中生成相同的数字,但在Windows中不生成 [英] <random> generates same number in Linux, but not in Windows

查看:118
本文介绍了<随机>在Linux中生成相同的数字,但在Windows中不生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码旨在生成一个在[1,100]区间内的五个伪随机数列表。我使用 time(0)来播种 default_random_engine ,这会在 unix time 。当我使用Microsoft Visual Studio 2013在Windows 7上编译和运行此程序时,它按预期工作(请参见下文)。然而,当我在Arch Linux和g ++编译器中这样做时,它的行为很奇怪。



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



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

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

除此之外,第一个数字会周期性递增1在Linux上。在获得上述输出之后,我等了大约30分钟,然后再次尝试发现第一个数字已经改变,现在总是以26为单位生成。它继续周期性地增加1,现在为32.它似乎对应于与变化的值 time(0)



为什么第一个数字在运行中很少发生变化,然后当它的时候,增加1?



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

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

使用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'<< 系统时间<< endl
<< -------------------<< ENDL; (int counter = 1; counter< = 5; counter ++)


$ b b
$ b b秘密= u(e);
cout<<秘密<< '\t'<< system_time<< ENDL;
}

系统(暂停);
返回0;


解决方案

这是发生了什么事:<在libstdc ++(GCC标准库)中的/ b>


  • default_random_engine 是<$ c $这是一个简单的线性同余引擎:

      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 s仅相差16807将在[1,100]中产生相同的数字这个程序。事实上,人们会预计产生的数字每21474836/16807 = 1278秒或21.3分钟就会增加一次,这与您的观察结果相符。




MSVC的 default_random_engine mt19937 ,它没有这个问题。 / p>

The code below is meant to generate a list of five pseudo-random numbers in the interval [1,100]. I seed the default_random_engine with time(0), which returns the system time in unix time. When I compile and run this program on Windows 7 using Microsoft Visual Studio 2013, it works as expected (see below). When I do so in Arch Linux with the g++ compiler, however, it behaves strangely.

In Linux, 5 numbers will be generated each time. The last 4 numbers will be different on each execution (as will often be the case), but the first number will stay the same.

Example output from 5 executions on Windows and Linux:

      | 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

Adding to the mystery, that first number periodically increments by one on Linux. After obtaining the above outputs, I waited about 30 minutes and tried again to find that the 1st number had changed and now was always being generated as a 26. It has continued to increment by 1 periodically and is now at 32. It seems to correspond with the changing value of time(0).

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

The code. It neatly prints out the 5 numbers and the system time:

#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;
}

解决方案

Here's what's going on:

  • default_random_engine in libstdc++ (GCC's standard library) is minstd_rand0, which is a simple linear congruential engine:

    typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647> minstd_rand0;
    

  • The way this engine generates random numbers is xi+1 = (16807xi + 0) mod 2147483647.

  • Therefore, if the seeds are different by 1, then most of the time the first generated number will differ by 16807.

  • The range of this generator is [1, 2147483646]. The way libstdc++'s uniform_int_distribution maps it to an integer in the range [1, 100] is essentially this: generate a number n. If the number is not greater than 2147483600, then return (n - 1) / 21474836 + 1; otherwise, try again with a new number.

    It should be easy to see that in the vast majority of cases, two ns that differ by only 16807 will yield the same number in [1, 100] under this procedure. In fact, one would expect the generated number to increase by one about every 21474836 / 16807 = 1278 seconds or 21.3 minutes, which agrees pretty well with your observations.

MSVC's default_random_engine is mt19937, which doesn't have this problem.

这篇关于&LT;随机&GT;在Linux中生成相同的数字,但在Windows中不生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆