以下代码段摘自a Pseudo-random number generator (written in ActionScript 3):
public function random():Number {
_currentSeed = (_currentSeed * 16807) % 2147483647);
return (_currentSeed/0x7FFFFFFF) + 0.000000000233;
}
代码的第一行很容易理解,它是标准linear congruential generator,乘数为16807
。第二行的第一部分将结果整数转换为大致在0
和1
之间的浮点数。
但是,第二行的最后一部分+ 0.000000000233
的目的是什么?在这样的RNG中是否有必要,或者它是否有不同的用途?
答案 0 :(得分:3)
如果您查看公式的其余部分,您会发现_currentSeed
0
值0
将始终产生相同的(0.5/0x7fffffff)
值。添加0
可以防止它卡在>= 1
上,但又小到可以阻止它返回值{{1}}。
公平地说,我在六年多前写过这段代码,所以我可能记得错了,但我确信这是推理。
答案 1 :(得分:1)
算法的大部分是well-known素数模乘法线性同余生成器。所有这些前缀形容词意味着它实现了最大周期长度而没有广义LCG所具有的附加项,因此PMMLCG可以追溯到1950年代,因为每次调用只减少了一次操作。你永远不应该将_currentSeed
初始化为零,并且如果正确实现和播种,算法的设计永远不会产生零或负数,因为它基于整数算术,这是精确的。 (正确的实现意味着确保结果不受整数溢出的影响。一个可移植的算法是由Linus Schrage在1959年在FORTRAN中编写的,还有一个简单的测试,包括1000次迭代后种子值应该是什么。 )
幻数比(1/2) / 0x7fffffff
略大,所以它不应该将返回值超过1.因为它没有被添加到_currentSeed
,所以它在避免修复时没有任何作用 - 如果将_currentSeed
设置为零,则会发生点行为。老实说,我看不出它正在完成任何事情。
答案 2 :(得分:-1)
我认为,出于某种原因,_currentSeed
可能是负值,因为_currentSeed
是有符号整数。将0.000000000233
(0.5/0x7fffffff
)添加到该值可以避免这种情况。