播种多个随机数发生器

And*_*rew 6 .net c# random thread-safety

我最近在另一篇文章的评论中讨论了相同类型的多个随机数生成器的初始化,在讨论中我们询问了以下问题:

1)使用不同的种子创建相同随机数生成器的多个实例并在程序的不同部分使用这些随机数生成器是一个好主意吗?

2)特别是,使用.Net Random类创建随机数生成器的技术,如下所示,并在不同的程序上下文中使用每个RNG会导致问题:

int size = 64;  // The number of RNGs to use
int seed;       // Get seed using some normal technique
Random[] r = new Random[size];

for (int i = 0; i < size; i++)
{
    r[i] = new Random(seed + i);
}
Run Code Online (Sandbox Code Playgroud)

3)如果需要多个随机数流,你会建议什么?

4)当需要线程安全时,您如何建议生成随机数?

And*_*rew 13

1)使用不同的种子创建相同随机数生成器的多个实例并在程序的不同部分使用这些随机数生成器是一个好主意吗?

.一般不推荐上述方案.

在他的书"计算机编程的艺术",第2卷:研究数学算法.Addison-Wesley,Reading,MA,第三版,1997,Knuth博士指出

发明一个万无一失的随机数源并不容易.

在这种情况下,我指出从随机序列中获取子序列可能比原始随机数序列更不随机:

请注意,Micosoft的Random实现基于subractive lagged-fibonacci生成器:

这种随机数发生器以内置的三点相关性着称,毕竟我们正在生成下一个随机数: 减法滞后 - 斐波纳契生成器

这些随机数发生器也在很大程度上依赖于它们的初始55数状态的初始化.初始化不佳可能导致随机数较差.在上述情况下,类似的状态可能导致来自每个不同随机数发生器的相关随机数.微软甚至在他们的MSDN帖子中建议不要使用System.Random:MSDN System.Random类和线程安全:

我们建议您创建一个Random实例来生成应用程序所需的所有随机数,而不是实例化单个Random对象.

我们将看一个例子,其中特定的初始化在不同的随机数生成器之间创建强相关性并寻找替代方案.

2)我已经实现了一个程序,试图初始化64个如上所述的Random实例,以便我们观察到任何可见的缺陷.我选择了一个特定的初始化作为概念证明:

int size = 64;    // The number of random numbers generators
int length = 20;  // The number of random numbers from each generator
int steps = 18;   // Move 18 steps forward in the beginning to show a particular phenomenon

Random[] r = new Random[size];

for (int i = 0; i < size; i++)
{
     r[i] = new Random(i + 1);

     // move RNG forward 18 steps
     for (int j = 0; j < steps; j++)
     {
          r[i].Next(3);
     }
}


for (int i = 0; i < size; i++)
{
     for (int j = 0; j < length; j++)
     {
          Console.Write(r[i].Next(3) + ", ");  // Generate a random number, 0 represents a small number, 1 a medium number and 2 a large number
     }

     Console.WriteLine();
}
Run Code Online (Sandbox Code Playgroud)

此程序生成此处显示的输出,每行代表另一个RNG的输出:

该计划的输出

请注意突出显示的列:在RNG似乎同步的特定位置,并产生彼此不相互独立的输出.

我还想补充一点,即创建一个随机数列表并从每行列表中取一个随机数也会产生看起来很差的随机数(这里使用的RNG毕竟已经失败了一些统计数据!) .

3)使用的RNG类型取决于您的背景.有些人可能对上述输出感到满意.在其他情况下,使用的RNG可能无法使用(蒙特卡罗模拟和密码学是两种情况,即使对于一个随机数流,也不应使用System.Random ).

如果您需要提取随机数的多个子序列,请找到为此目的设计的RNG:

4)最后,如果我想在多个线程中使用System.Random怎么办?Microsoft MSDN在我上面提到的相同链接中有答案: