随机(Java 7)中的181783497276652981和8682522807148012是什么?

为什么在Random.java中选择了1817834972766529818682522807148012

以下是来自Java SE JDK 1.7的相关源代码:

/**
*创建一个新的随机数生成器。此构造函数设置
*随机数生成器的种子很可能是一个值
*与此构造函数的任何其他调用不同。
*/
公共随机{
这(seedUniquifier()^System.nanoTime());
}
私有静态长种子uniquifier(){
//L'Ecuyer,“线性同余生成元表”
//不同尺寸和良好的晶格结构”,1999年
对于(;;){
长电流=seedUniquifier.get();
长下一个=当前*181783497276652981L;
if(种子Uniquifier.compareAndSet(当前,下一个))
下一步返回;
}
}
专用静态最终原子长种子唯一限定符
=新原子长(8682522807148012L);

因此,在没有任何seed参数的情况下调用new Random(),将获取当前的“seed uniquifier”,并将其与System.nanoTime()异或。然后使用181783497276652981创建另一个种子uniquifier,以便下次调用new Random()时存储

文本181783497276652981L8682522807148012L不放在常量中,但它们不会出现在其他任何地方

起初,这个评论给了我一个简单的线索。在线搜索该文章将生成实际的文章8682522807148012没有出现在论文中,但是,181783497276652981确实出现了——作为另一个数字的子串,1181783497276652981,即181783497276652981,前面加了1

本文声称,1181783497276652981是一个对线性同余生成器产生良好“优点”的数字。这个数字只是被错误地复制到Java中了吗?181783497276652981是否具有可接受的优点

为什么选择了8682522807148012

在线搜索任何一个数字都不会产生任何解释,只有此页面也会注意到181783497276652981前面已删除的1

是否可以选择其他与这两个数字同样有效的数字?为什么

  1. 这个数字只是被错误地复制到Java中了吗

    是的,好像是打字错误

  2. 181783497276652981是否具有可接受的优点

    这可以使用本文提出的评估算法来确定。但“原始”数字的优点可能更高

  3. 为什么选择8682522807148012

    似乎是随机的。它可能是编写代码时System.nanoTime()的结果

  4. 是否可以选择其他与这两个数字同样有效的数字

    并不是每个数字都一样“好”。所以,不

播种策略

JRE的不同版本和实现之间的默认种子模式存在差异

public Random(){this(System.currentTimeMillis());}
public Random(){this(++seedUniquifier+System.nanoTime());}
public Random(){this(seedUniquifier()^System.nanoTime());}

如果您在一行中创建多个RNG,则第一个RNG是不可接受的。如果它们的创建时间在相同的毫秒范围内,它们将给出完全相同的序列。(相同的种子=>相同的序列)

第二个不是线程安全的。当同时初始化时,多个线程可以获得相同的RNG。此外,后续初始化的种子往往是相关的。根据系统的实际计时器分辨率,种子序列可以线性增加(n,n+1,n+2,…)。正如《随机种子需要有多大的不同》中所述?而参考文献中伪随机数发生器初始化的常见缺陷是,相关种子可以在多个RNG的实际序列之间产生相关性

第三种方法创建随机分布的、因此不相关的种子,甚至跨线程和后续初始化。
因此,当前的java文档:

此构造函数将随机数生成器的种子设置为
值很可能不同于此函数的任何其他调用
构造器

可以通过“跨线程”和“不相关”进行扩展

种子序列质量

但种子序列的随机性仅与基础RNG一样好。
此java实现中用于种子序列的RNG使用c=0和m=2^64的乘法线性同余生成器(MLCG)。(模2^64由64位长整数的溢出隐式给出)
由于c为零和2模幂,因此“质量”(周期长度、位相关性等)受到限制。正如文章所说,除了整体循环长度外,每个位都有自己的循环长度,对于低有效位,循环长度呈指数下降。因此,较低的位具有较小的重复模式。(seedUniquifier()的结果应进行位反转,然后在实际RNG中将其截断为48位)

但是它很快!为了避免不必要的比较和设置循环,循环体应该是快速的。这可能解释了这个特定MLCG的用法,没有加法,没有xoring,只有一次乘法

上面提到的论文给出了一个c=0和m=2^64的良好“乘数”列表,如1181783497276652981

总而言之:这是@JRE开发者的一项努力;)但是有一个拼写错误。
(但谁知道呢,除非有人对其进行评估,否则缺失的前导1实际上有可能改善播种RNG。)

但某些乘数肯定更糟糕:
“1”表示一个恒定的序列。
“2”导致单位移动序列(以某种方式相关)

RNG的序列间相关性实际上与(Monte Carlo)模拟相关,其中多个随机序列被实例化甚至并行化。因此,为了获得“独立”的模拟运行,需要一个良好的播种策略。因此,C++11标准引入了种子序列的概念,用于生成不相关的种子

发表评论