来自wikipedia(@helloworld922 发布的引用所暗示的引用):
LCG 的另一个问题是,如果 m 设置为 2 的幂,则生成序列的低位比特的周期比整个序列的周期短得多。通常,基 b 表示中的第 n 个最低有效位输出序列,其中对于某个整数 k,bk = m,最多以周期 bn 重复。
此外,它继续(我的斜体):
当 m 是 2 的幂时,LCG 的低位位不应依赖于任何程度的随机性。实际上,简单地用 2n 代替模数项表明低位比特经历了非常短的周期。特别是,当 m 是 2 的幂时,任何全周期 LCG 都会交替产生奇数和偶数结果。
最后,原因可能是历史原因:Sun 的人想要可靠地工作,而 Knuth 公式给出了 32 个有效位。请注意,java.util.Random
API 是这样说的(我的斜体字):
如果使用相同的种子创建 Random 的两个实例,并且为每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。为了保证这一特性,为类 Random 指定了特定的算法。为了 Java 代码的绝对可移植性,Java 实现必须使用此处为类 Random 显示的所有算法。但是,允许类 Random 的子类使用其他算法,只要它们遵守所有方法的通用合同。
因此,我们坚持将其作为参考实现。然而,这并不意味着你不能使用另一个生成器(和子类 Random 或创建一个新类):
来自同一个维基百科页面:
MMIX by Donald Knuth m=2 64 a=6364136223846793005 c=1442695040888963407
有一个 64 位公式适合您。
java.util.Random
随机数很棘手(正如 Knuth 所指出的),根据您的需要,如果您需要一个 64 位数字,您可能只需调用两次并将位连接起来就可以了。如果您真的关心统计属性,请使用Mersenne Twister之类的东西,或者如果您关心信息泄漏/不可预测性,请使用java.security.SecureRandom
。