我最近在另一篇文章的评论中讨论了相同类型的多个随机数生成器的初始化,在该讨论中我们提出了以下问题:
1) 用不同的种子创建同一个随机数生成器的多个实例并在程序的不同部分使用这些随机数生成器是个好主意吗?
2) 特别是,使用 .Net Random 类创建随机数生成器的技术是否会产生问题:
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.
在这种情况下,我指出从随机序列中提取子序列可能不如原始随机数序列随机:
请注意,Micosoft 的 Random 实现基于减法滞后斐波那契生成器:
这种随机数生成器以内置的三点相关性着称,毕竟我们要生成下一个随机数:
这些随机数生成器在很大程度上也依赖于其初始 55 个数字状态的初始化。初始化不良可能会导致随机数不良。在上述情况下,相似的状态可能会导致来自每个不同随机数生成器的相关随机数。 Microsoft 甚至在他们关于 System.Random 的 MSDN 帖子中反对这样做:MSDN The System.Random class and thread safety :
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:
4) 最后,如果我想在多线程中使用 System.Random 怎么办? Microsoft MSDN 在我上面提到的同一链接中有答案:
关于c# - 播种多个随机数生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36376888/