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