受到this和类似问题的启发,我想了解C ++ 11中的mt19937伪数生成器如何表现,当在两台独立的机器中时,它使用相同的输入进行播种。
换句话说,我们有以下代码;
std::mt19937 gen{ourSeed};
std::uniform_int_distribution<int> dest{0, 10000};
int randNumber = dist(gen);
如果我们在不同的时间在不同的机器上尝试此代码,我们每次都会获得相同的randNumber值序列或不同的序列吗?
在任何一种情况下,为什么会出现这种情况?
另一个问题:
无论种子如何,此代码是否会无限地生成随机数?我的意思是,例如,如果我们在一个运行数月但没有停止的程序中使用这个代码块,那么数字的生成或数字的一致性会有问题吗?
答案 0 :(得分:8)
生成器将生成相同的值。
发行版可能不会,至少在不同的编译器或库版本中。该标准未将其行为指定为该详细程度。如果您希望编译器和库版本之间保持稳定,则必须滚动自己的发行版。
禁止库/编译器更改,它将以相同的顺序返回相同的值。但如果你关心自己编写的发行版。
...
所有PRNG都有模式和期限。 mt19937以2 ^ 19937-1的周期命名,这不太可能成为问题。但其他模式可以发展。 MT PRNG对许多统计测试都很强大,但它们不是密码学上安全的PRNG。
因此,如果您运行数月,这将成为一个问题将取决于您发现的问题的具体细节。但是,mt19937将是一个比你自己写的更好的PRNG。但假设攻击者可以根据过去的证据预测其未来的行为。
答案 1 :(得分:2)
无论种子如何,此代码是否会无限地生成随机数?我的意思是,例如,如果我们在一个运行数月但没有停止的程序中使用这个代码块,那么数字的生成或数字的一致性会有问题吗?
我们处理标准C ++的RNG称为伪随机RNG。根据定义,这是纯计算设备,具有多位状态(您可以将状态视为大位向量)和三个函数:
就是这样。显然,状态具有有限的大小,在MT19937的情况下为19937位,因此状态总数为2 19937 因此MT19937 next_state()函数是周期性的,最大周期不超过2 19937 。这个数字真的很大,而且很可能足以进行典型的模拟
但输出最大为64位,因此输出空间为2 64 。这意味着在大型运行期间,任何特定输出都会出现很多次。重要的是,当不仅会出现一些64位数字,而是之后的数字,之后以及之后 - 这就是您知道RNG期限的时间。
如果我们在不同的时间在不同的机器上尝试此代码,我们每次都会获得相同的randNumber值序列或不同的序列吗?
生成器的定义非常严格,您将获得相同的位流。例如,来自C ++标准(https://timsong-cpp.github.io/cppwp/rand)
的MT19937class mersenne_twister_engine {
...
static constexpr result_type default_seed = 5489u;
...
和函数seed2state描述为(https://timsong-cpp.github.io/cppwp/rand#eng.mers-6)
效果:构造一个mersenne_twister_engine对象。将X -n 设置为值mod 2 w 。然后,迭代地为i = -n,...,-1,将X i 设置为...
函数next_state与第10000次调用时的测试值一起描述。标准说(https://timsong-cpp.github.io/cppwp/rand#predef-3)
using mt19937 = mersenne_twister_engine<uint_fast32_t,32,624,397,31,0x9908b0df,11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253>;
3
#Required behavior: The 10000th consecutive invocation of a default-constructed object
of type mt19937 shall produce the value 4123659995.
我使用的四大编译器(GCC,Clang,VC ++,Intel C ++)产生了相同的MT19937输出。
另一方面,发行版没有很好地指定,因此在编译器和库之间有所不同。如果您需要可移植的发行版,您可以自己动手或使用Boost或类似库中的内容
答案 2 :(得分:0)
任何带有种子的伪RNG都会在每台机器上为每次相同的种子提供相同的序列。发生这种情况,因为生成器只是一个(复杂的)数学函数,并且实际上没有任何关于它的随机性。大多数情况下,当你想要随机化时,你会从系统时钟中获取种子,这会不断变化,因此每次运行都会有所不同。 在计算机游戏中使用相同的序列是很有用的,例如当你有一个随机生成的世界并且想要生成完全相同的世界时,或者避免人们在随机机会的游戏中使用保存游戏作弊。