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)如果需要多个随机数流,你会建议什么?
解决方法
不可以.一般不推荐上述方案.
在他的书“计算机编程的艺术”,第2卷:研究数学算法. Addison-Wesley,Reading,MA,第三版,1997,Knuth博士指出
It is not easy to invent a foolproof source of random numbers.
在这种情况下,我指出从随机序列中获取子序列可能比原始随机数序列更不随机:
请注意,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毕竟已经失败了一些统计数据!) .
3)使用的RNG类型取决于您的背景.有些人可能对上述输出感到满意.在其他情况下,使用的RNG可能无法使用(蒙特卡罗模拟和密码学是两种情况,即使对于一个随机数流,也不应使用System.Random).
如果您需要提取随机数的多个子序列,请找到为此目的设计的RNG:
> PCG
4)最后,如果我想在多个线程中使用System.Random怎么办?
Microsoft MSDN在我上面提到的相同链接中有答案: