C++ 为什么在我';你给发电机设定了时间种子?

C++ 为什么在我';你给发电机设定了时间种子?,c++,C++,我不明白为什么我已经用time(0)(C++初级读本告诉我使用time(0))为default\u random\u引擎)播种了一个time(0),却一直得到相同的第一位数字。这是我电脑的问题吗?(Ubuntu,C++11) 我试过一个在线编译器,有趣的是,我用gcc得到了相同的第一位数字,而不用clang++ 代码: #包括 #包括 #包括 使用名称空间std; int main(){ 自动t=时间(0); cout您正在为随机生成器设置非常相似的初始状态。根据生成器的质量,这可能会或可能不

我不明白为什么我已经用
time(0)
(C++初级读本告诉我使用
time(0)
)为
default\u random\u引擎
)播种了一个
time(0)
,却一直得到相同的第一位数字。这是我电脑的问题吗?(Ubuntu,C++11)

我试过一个在线编译器,有趣的是,我用
gcc
得到了相同的第一位数字,而不用
clang++

代码:

#包括
#包括
#包括
使用名称空间std;
int main(){
自动t=时间(0);

cout您正在为随机生成器设置非常相似的初始状态。根据生成器的质量,这可能会或可能不会导致类似的输出。为了说明,我将您的示例扩展为(a)仅打印第一个序列,因为这是我们关心的,以及(b)打印不同分辨率的多个结果:

int main(){
    auto t = time(0);
    cout << "time: " << t << endl;
    default_random_engine e(t);
    default_random_engine e2(t);
    default_random_engine e3(t);
    default_random_engine e4(t);
    uniform_int_distribution<int> uniform_dist(0, 9);
    uniform_int_distribution<int> uniform_dist2(0,999);
    uniform_int_distribution<int> uniform_dist3(0,99999);
    uniform_int_distribution<int> uniform_dist4(0,9999999);
    cout << "sequence: ";
    cout << uniform_dist(e) << " " << uniform_dist2(e2) << " " << uniform_dist3(e3) << " " << uniform_dist4(e4);
    cout << endl;
    return 0;
}
虽然我不知道这个随机生成器实现到底在做什么,但您可以很容易地看到,它正在执行一个非常简单的转换,将种子转换为状态,并将状态转换为输出值。正如其他评论所建议的,有更好的随机生成器和更好的种子。另外请注意,实现之间的质量有所不同选项;Visual Studio 2017没有表现出这种行为。

正如评论中所建议的,与
time()
相比,将提供更优质的种子材料来源

但是,如果需要使用带有线性同余生成器的小种子,则可以扩展种子值以生成更好的初始值设定项。线性生成器在重新分配种子值中的位时速度较慢,因此微小的差异将导致初始的几个值彼此接近

标准库提供了将小种子扩展为更好初始值的函数:

seed_seq seed({t});
default_random_engine e(seed);

这是问题之一,尤其是在可供选择的数字有限的情况下。您可能可以通过使用更好的引擎(如
mt19937
)来改进它。我还建议您查看。使用
时间(0)
与使用
std::random\u设备不同,种子值没有那么大的不同。如果您仍然想使用
time(0)
可以调用
e.discard(n)
其中
n
是要提升生成器状态的步数。如果有效,则丢弃初始
n
值。如果
std::default_random_引擎
实现为
rand
,则
时间(0)
不会产生完全不同的种子,这将导致一个接近最后一个种子的随机序列。远离
std::default\u random\u engine
,因为你不知道它是什么。除非你真的需要性能,否则我会默认使用
std::mt19937
作为你去PRNG的工具,不一样,但很接近。
1541162550
1541162552
没有太大区别,后者可能与坏的PRNGIt有很大关系。这实际上取决于生成器。可以想象,种子的最高有效位对生成器的初始状态有更大的影响。我的建议是,使用更好的种子,如
std::random_设备
,或者使用
光盘ard()
在使用前“预热”发电机。伙计,这个实验非常聪明和简单。非常全面,谢谢。作为一个小小的改进,时间(0)可以输入std::mt19937(编辑:我现在看到几乎所有其他人都已经推荐了这个).在x86_64上的g++和clang++中,
std::default_random_引擎
std::linear_conformential_引擎
的类型定义。
$ ./a.out
time: 1541162210
sequence: 7 704 70457 7070079
$ ./a.out
time: 1541162211
sequence: 7 704 70457 7070157
$ ./a.out
time: 1541162212
sequence: 7 704 70458 7070236
$ ./a.out
time: 1541162213
sequence: 7 704 70459 7070315
$ ./a.out
time: 1541162214
sequence: 7 704 70460 7070393
$ ./a.out
time: 1541162215
sequence: 7 704 70461 7070472
$ ./a.out
time: 1541162216
sequence: 7 704 70461 7070550
$ ./a.out
time: 1541162217
sequence: 7 704 70462 7070629
$ ./a.out
time: 1541162218
sequence: 7 704 70463 7070707
$ ./a.out
time: 1541162219
sequence: 7 704 70464 7070786
seed_seq seed({t});
default_random_engine e(seed);