c# – 播种多个随机数发生器

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

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);
}

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

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

解决方法

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

不可以.一般不推荐上述方案.

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

It is not easy to invent a foolproof source of random numbers.

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

> Random Numbers
> PCG

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

> Reference Source – System.Random

这种随机数发生器以内置的三点相关性着称,毕竟我们正在生成下一个随机数:

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

Instead of instantiating individual Random objects,we recommend that you create a single Random instance to generate all the random numbers needed by your app.

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

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();
}

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

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

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

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

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

> PCG

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

> MSDN The System.Random class and thread safety

相关文章

项目中经常遇到CSV文件的读写需求,其中的难点主要是CSV文件...
简介 本文的初衷是希望帮助那些有其它平台视觉算法开发经验的...
这篇文章主要简单记录一下C#项目的dll文件管理方法,以便后期...
在C#中的使用JSON序列化及反序列化时,推荐使用Json.NET——...
事件总线是对发布-订阅模式的一种实现,是一种集中式事件处理...
通用翻译API的HTTPS 地址为https://fanyi-api.baidu.com/api...