这个神奇数字的目的是什么?



以下代码片段取自伪随机数生成器(在ActionScript 3中编写):

public function random():Number {
    _currentSeed = (_currentSeed * 16807) % 2147483647);
    return (_currentSeed/0x7FFFFFFF) + 0.000000000233;
}

代码的第一行很容易理解,它是一个标准的线性同余生成器,乘数为16807。第二行第一部分将结果整数转换为大致介于01之间的浮点数。

然而,第二行最后一部分+ 0.000000000233的目的是什么?在这样的RNG中这是必要的,还是有不同的目的?

如果您查看公式的其余部分,您将看到_currentSeed的值为0总是会导致0的值相同。添加(0.5/0x7fffffff),可以防止它在0上卡住,但也足够小,可以防止它返回值>= 1

公平地说,这段代码是我6年前写的,所以我可能记错了,但我相当确定这就是原因。

算法的主体是一个著名的素数模乘线性同余生成器。所有这些前缀形容词都意味着它实现了最大的周期长度,而不像广义lcg那样有附加的术语,所以pmmlcg在20世纪50年代就很流行,因为每次调用可以减少一次操作。您永远不应该将_currentSeed初始化为零,并且如果正确实现和播种,该算法被设计为永远不会产生零或负数,因为它基于整数算术,这是精确的。(正确的实现意味着确保结果不受整数溢出的影响。Linus Schrage早在1959年就用FORTRAN编写了一个可移植的算法,附带了一个简单的测试,包含了1000次迭代后的种子值应该是多少。

魔术数字比(1/2) / 0x7fffffff稍大,所以它不应该将返回值推到1以上。因为它没有被添加到_currentSeed中,所以它在避免当_currentSeed被设置为零时可能发生的定点行为方面没有任何作用。老实说,我看不出它有什么用。

我认为,出于某种原因,_currentSeed可能是一个负值,因为_currentSeed是一个有符号整数。在值中添加0.000000000233 (0.5/0x7fffffff)可以避免这种情况。

相关内容

  • 没有找到相关文章

最新更新