使用连续种子生成均匀的随机数?

时间:2014-06-29 14:54:08

标签: c++ c++11 random

我有一个有趣的问题,即

通过在标准库(或任何其他随机生成器)中使用着名的mersenne twister std::mt19937 r并使用种子r.seed(4)进行设置,例如,可以获得均匀随机生成的数字(在uint_fast32_t提供的范围内。

如果我们从1到100遍历种子并生成第一个随机数,究竟会发生什么?这个序列是否仍然均匀分布?

for(int i = 0;i<100;i++){
   r.seed(i);
   int v = r();
}

我有一些算法通过使用这个技巧更容易实现,而不是以通常的方式生成数字(每次都不重置种子)。

我实际上并不相信通过滥用这样的发生器,可以保持序列的均匀性。

有没有人有专业知识给出一些推理?

非常感谢!

1 个答案:

答案 0 :(得分:2)

此代码按照您的说法执行,在每个数字生成之间重置种子:

#include <iostream>
#include <random>

int main ()
{
    std::mt19937 r; 

    for(int i = 0;i<10;i++){
       r.seed(i);
       int v = r();
        std::cout << v << std::endl;
    }
    return 0;
}

此计划的输出确定性。您不断重置每一代之间的状态(此状态用于生成下一个随机数)。您完全不能保证从不同的mersenne序列生成的数字的分布或均匀性(同样,每次重置种子时都会启动一个新序列)。

如果您的目标是生成限制在某个时间间隔内的统一分布,请使用std::uniform_real_distribution

Example from en.cppreference.com

#include <random>
#include <iostream>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(1, 2);
    for (int n = 0; n < 10; ++n) {
        std::cout << dis(gen) << ' ';
    }
    std::cout << '\n';
}

它在C ++标准中定义,§26.5.8.2.2部分:

  

uniform_real_distribution随机数分布产生随机   数字x,a≤x< b,按常数分配   概率密度函数p(x | a,b)= 1 /(b - a)