C# 播种多个随机数生成器

C# 播种多个随机数生成器,c#,.net,random,thread-safety,C#,.net,Random,Thread Safety,我最近在另一篇帖子的评论中讨论了同一类型多个随机数生成器的初始化,在讨论中,我们提出了以下问题: 1) 用不同的种子创建同一个随机数生成器的多个实例,并在程序的不同部分使用这些随机数生成器,这是一个好主意吗 2) 特别是,使用.Net随机类(种子如下)创建随机数生成器并在不同程序上下文中使用每个RNG的技术是否会导致问题: int size = 64; // The number of RNGs to use int seed; // Get seed using some nor

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

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

2) 特别是,使用.Net随机类(种子如下)创建随机数生成器并在不同程序上下文中使用每个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);
}
int size=64;//要使用的RNG数
int seed;//使用一些常规技术获取种子
Random[]r=新随机[大小];
对于(int i=0;i
3) 如果需要多个随机数流,您会推荐什么

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

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

不会。一般不建议采用上述方案

在他的书《计算机编程的艺术》第二卷:半数值算法中。Addison Wesley,雷丁,马萨诸塞州,第三版,1997年,Knuth博士指出

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

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

请注意,Micosoft的随机实现是基于一个欠拉滞后斐波那契生成器的:

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

这些类型的随机数生成器也严重依赖于其初始55个数状态的初始化。初始化不良可能导致随机数不良。在上述情况下,类似状态可能导致来自每个不同随机数生成器的相关随机数。微软甚至在其MSDN关于系统的帖子中建议不要这样做。随机::

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

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

2) 我已经实现了一个程序,尝试初始化上面描述的64个随机实例,以便我们观察任何可见的缺陷。我选择了一个特定的初始化作为概念证明:

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();
}
int size=64;//随机数生成器的数目
整数长度=20;//每个生成器的随机数
int steps=18;//在开始时向前移动18步以显示特定的现象
Random[]r=新随机[大小];
对于(int i=0;i
此程序生成此处所示的输出,每行表示另一个RNG的输出:

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

我还想补充一点,创建一个单一的随机数列表并从每行列表中提取一个随机数也会产生外观不佳的随机数(这里使用的RNG毕竟在某些统计方面失败了!)

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

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

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

不确定“多个随机数流”是什么意思。在随机数中,任意两个随机数之间没有关系,没有顺序,每个随机数都是独立的实例


如果使用加密PRNG,则无需种子设定。考虑到.NET./P>这个问题是作为对以下问题的回答而对评论的回答而产生的:这比你的任何评论都更有说服力。虽然在任何时候只有3个数字可供选择,但这并不令人惊讶。(例如,如果您在
Next(100)
中显示了相同的模式,这将更加令人惊讶。@JonSkeet这已经足够令人惊讶了。这个想法是显示高、中、低数字。RNG决定“同时”输出大的数字。在第二列之后,还有一列我遗漏了。13个数字同时“小”的概率(如第二列所示)约为150万分之一。通常你会使用类似的随机数在几个动作之间进行选择或模拟掷骰子。(而且,我从来没有在评论中添加过这么多的参考文献和信息——它们实际上就是评论。)我从我的回答中添加了一个链接到这篇文章。这感觉就像是一个使用连续种子的问题