【发布时间】:2013-08-08 04:00:24
【问题描述】:
为什么在Random.java 中选择了181783497276652981 和8682522807148012?
以下是 Java SE JDK 1.7 的相关源代码:
/**
* Creates a new random number generator. This constructor sets
* the seed of the random number generator to a value very likely
* to be distinct from any other invocation of this constructor.
*/
public Random() {
this(seedUniquifier() ^ System.nanoTime());
}
private static long seedUniquifier() {
// L'Ecuyer, "Tables of Linear Congruential Generators of
// Different Sizes and Good Lattice Structure", 1999
for (;;) {
long current = seedUniquifier.get();
long next = current * 181783497276652981L;
if (seedUniquifier.compareAndSet(current, next))
return next;
}
}
private static final AtomicLong seedUniquifier
= new AtomicLong(8682522807148012L);
因此,在没有任何种子参数的情况下调用new Random() 会获取当前的“种子唯一性”并与System.nanoTime() 进行异或。然后它使用181783497276652981 创建另一个种子唯一标识符,以便在下次调用new Random() 时存储。
文字181783497276652981L 和8682522807148012L 没有放在常量中,但它们不会出现在其他任何地方。
起初,评论给了我一个简单的线索。在线搜索该文章会产生the actual article。 8682522807148012 没有出现在论文中,但181783497276652981 确实出现了——作为另一个数字1181783497276652981 的子字符串,它是181783497276652981,前面带有1。
论文声称1181783497276652981 是一个可以为线性同余生成器产生良好“优点”的数字。这个数字是否只是错误地复制到 Java 中? 181783497276652981 有可接受的优点吗?
为什么选择8682522807148012?
在网上搜索这两个数字都没有任何解释,只有this page 还注意到1 在181783497276652981 前面被丢弃。
是否可以选择与这两个数字一样有效的其他数字?为什么或为什么不?
【问题讨论】:
-
我只想指出,没有提到的常量(即使是开头的较大的常量)太大而无法容纳,尽管乘法肯定会导致溢出。跨度>
-
8682522807148012是该类先前版本的遗留物,如in the revisions made in 2010 所示。181783497276652981L似乎确实是一个错字,您可以提交错误报告。 -
要么是错字,即错误,要么是具有未公开动机的功能。你得问问作者。你在这里得到的任何东西都或多或少是不知情的意见。如果您认为这是一个错误,请提交错误报告。
-
特别是考虑到不同的答案,这可能是每个常数的两个独立问题。
-
很遗憾看到这样一个基础类中内置了全局可伸缩性瓶颈。
seedUniquifier在 64 核机箱上会变得非常有竞争力。线程本地会更具可扩展性。