不止一次播种伪随机数发生器的问题?

a03*_*56f 5 c++ random seed srand prng

我已经看到了很多关于每次执行不多次伪随机数生成器的建议,但从未附带过彻底的解释.当然,很容易理解为什么以下(C/C++)示例不是一个好主意:

int get_rand() {
  srand(time(NULL));
  return rand();
}
Run Code Online (Sandbox Code Playgroud)

因为get_rand每秒调用几次会产生重复的结果.

但是下面的例子不是一个可以接受的解决方案吗?

MyRand.h

#ifndef MY_RAND_H
#define MY_RAND_H

class MyRand
{
  public:
    MyRand();
    int get_rand() const;
  private:
    static unsigned int seed_base;
};

#endif
Run Code Online (Sandbox Code Playgroud)

MyRand.cpp

#include <ctime>
#include <cstdlib>
#include "MyRand.h"

unsigned int MyRand::seed_base = static_cast<unsigned int>(time(NULL));

MyRand::MyRand()
{
  srand(seed_base++);
}

int MyRand::get_rand() const
{
  return rand();
}
Run Code Online (Sandbox Code Playgroud)

main.cpp中

#include <iostream>
#include "MyRand.h"

int main(int argc, char *argv[]) 
{
  for (int i = 0; i < 100; i++) 
  {
    MyRand r;
    std::cout << r.get_rand() << " ";
  }
}
Run Code Online (Sandbox Code Playgroud)

即使MyRand:s构造函数快速连续多次调用,每次调用srand都有不同的参数.显然,这不是线程安全的,但后来也不是rand.

Jay*_*rod 6

每次调用伪随机数生成器函数时,生成器都会采用某种内部状态并生成伪随机数和新的内部状态.精心选择转换内部状态的算法,使输出看起来是随机的.

当您为随机数生成器播种时,您基本上就是设置此内部状态.如果将内部状态重置为某个可预测值,则会丢失随机性的外观.

例如,流行的简单RNG是线性同余生成器.数字生成如下:

X[n+1] = (a X[n] + c) mod m
Run Code Online (Sandbox Code Playgroud)

在这种情况下,X [n + 1]既是结果又是新的内部状态.如果您按照上面的建议每次播种生成器,您将获得如下所示的序列:

{(ab + c) mod m, (a(b+1) + c) mod m, (a(b+2) + c) mod m, ...}
Run Code Online (Sandbox Code Playgroud)

其中b是你的seed_base.这根本不是随机的.