<随机>在Linux中生成相同的数字,但在Windows中不生成 [英] <random> generates same number in Linux, but not in 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) isminstd_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 numbern
. 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
n
s 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.
这篇关于<随机>在Linux中生成相同的数字,但在Windows中不生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!