除了之前的答案:
System.Random 应该绝不用于科学和工程的模拟或数值求解器,因为不准确的模拟结果或收敛失败会产生重大的负面后果。这是因为 Microsoft 的实施在多个方面存在严重缺陷,并且由于兼容性问题,他们无法(或不会)轻易修复它。见this post。
所以:
如果存在不应该知道生成序列的对手,则使用RNGCryptoServiceProvider 或其他精心设计、实施和验证的加密强 RNG,并尽可能使用硬件随机性。 否则;
如果是需要良好统计属性的模拟等应用程序,请使用精心设计和实施的非加密 PRNG,例如 Mersenne Twister。 (在这些情况下,加密 RNG 也正确,但通常太慢且笨拙。) 否则;
仅如果数字的使用完全不重要,例如决定在随机幻灯片中接下来显示哪张图片,则使用System.Random。
我最近在进行蒙特卡罗模拟以测试不同使用模式对医疗设备的影响时非常明显地遇到了这个问题。模拟产生的结果与合理预期的结果相反。
有时你无法解释某事,背后有一个原因,而这个原因可能非常麻烦!
这是在越来越多的模拟批次中获得的 p 值图:
红色和洋红色图显示了两种使用模型在所研究的两个输出指标中差异的统计显着性。
青色图是一个特别令人震惊的结果,因为它代表了模拟的随机输入特征的p值。 (绘制此图只是为了确认输入没有错误。) 当然,输入在研究中的两个使用模型之间的设计相同,因此输入之间不应该有任何统计学上的显着差异 到两个模型。然而,在这里,我看到超过 99.97% 的信心有这样的差异!!
最初我认为我的代码有问题,但一切都检查过了。 (特别是我确认线程没有共享System.Random 实例。) 当重复测试发现这个意外结果高度一致时,我开始怀疑System.Random。
我用 Mersenne Twister 实现替换了System.Random—— 没有其他更改—— 输出立即变得截然不同,如下所示:
此图表反映了在此特定测试集中使用的参数的两种使用模型之间在统计上没有显着差异。这是预期的结果。
请注意,在第一个图表中,垂直对数刻度(在 p 值上)涵盖 七个十年,而第二个图表中只有一个十年——证明虚假差异的统计意义是多么明显! (垂直比例表示差异可能是偶然出现的概率。)
我怀疑发生的事情是 System.Random 在相当短的生成器周期内存在一些相关性,并且两个被测模型之间的内部随机抽样模式不同(对 Random.Next 的调用次数大不相同)导致这些以不同的方式影响这两个模型。
碰巧模拟输入来自与模型用于内部决策的相同RNG流,这显然导致这些采样差异影响输入。 (这实际上是一件幸运的事情,否则我可能没有意识到意外结果是软件故障,而不是被模拟设备的某些真实属性!)