我正在用Delphi编写一个撰写统计测试的程序(必须使用Delphi),听说Random功能有些奇怪。在程序启动时,必须调用randomize来随机化随机函数的种子。
我想知道在调用randomize后,random函数是否足够随机以进行统计测试,或者是否需要使用Mersenne Twister?是否有人了解随机数的实际实现情况,能告诉我这一点有多重要?
我正在用Delphi编写一个撰写统计测试的程序(必须使用Delphi),听说Random功能有些奇怪。在程序启动时,必须调用randomize来随机化随机函数的种子。
我想知道在调用randomize后,random函数是否足够随机以进行统计测试,或者是否需要使用Mersenne Twister?是否有人了解随机数的实际实现情况,能告诉我这一点有多重要?
Delphi的伪随机数生成器(PRNG)像几乎所有编程语言RTL PRNG一样,是线性同余生成器。
对于大多数小规模应用来说,这已经足够好了,但也需要注意一些问题。特别是要注意低位比特:乘法和加法的模式意味着低位比特并不是非常随机。但这个问题通常仅适用于从中提取出来并使用mod
或类似方法截断的大型32位值。在内部使用Random(10)
提取0到9之间的值时,将在整个32位范围内执行乘法而不是mod
运算。
我忍不住了。
Random
是否足够可靠取决于您打算使用它的上下文环境。Random
来获取各种空值分布、数据伪复制和重新采样。到目前为止,我在自己的代码中没有遇到过任何情况,其中Random
会产生偏倚或不可靠的结果,或者结果会排除其用于预期的统计测试。但是,适用于我的代码的内容不一定适用于您的代码。Random
的结果进行统计分析(例如在R、SPSS等软件中),并检查结果的分布是否违反您特定统计测试的分布要求。(如果您是一名合格的科学家,这本来就是您应该做的。)在这些函数中,还有一个具有密码学强度的随机数生成器。这是软件中获得的最好的随机性,因为它基于非常长的因素列表进行自我种子化。我不确定,但我怀疑它甚至会使用硬件随机数生成器(如果您有)。
如果这还不够,您还可以尝试注册Quantum Random Bit Generator Service以获取一些真正的随机值。
从 Embarcadero 网站上得知:
_lrand 是长随机数生成函数。_rand 使用一个乘法同余随机数生成器,周期为 2^64,以返回在范围从 0 到 2^31 - 1 的连续伪随机数。
通过使用 srand 函数并传入参数值 1 来重新初始化生成器。可以通过使用给定的种子数字调用 srand 函数来将其设置为新的起始点。
Randseed:=int32(Randseed*$08088405)+1
result:=Randseed*Range shr 32
(伪代码/假设乘法是在任意大的整数上进行)
返回0至9之间的随机数
StrToInt(copy(FloatToStr(Random),4,1))