为什么181783497276652981
和8682522807148012
在选择Random.java
?
以下是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
不会放置在常量中,但是它们不会出现在其他任何地方。
起初,评论给了我一个轻松的线索。在线搜索该文章会产生实际的文章。
8682522807148012
没有出现在纸上,但181783497276652981
确实出现-
作为另一个号码,一个子1181783497276652981
,这是181783497276652981
一个1
前缀。
该论文声称,1181783497276652981
这个数字对于线性同余生成器具有良好的“优点”。这个数字是否只是被错误地复制到Java中?是否181783497276652981
有一个可以接受的优点?
为什么8682522807148012
选择了?
在线搜索任何一个数字都不会产生任何解释,只有该页面还注意到1
前面的掉落181783497276652981
。
是否可以选择其他与这两个数字一样有效的数字?为什么或者为什么不?
这个数字是否只是被错误地复制到Java中?
是的,似乎是一个错字。
181783497276652981是否具有可接受的优点?
这可以使用本文提出的评估算法确定。但是“原始”数字的优点可能更高。
为什么选择8682522807148012?
似乎是随机的。编写代码时可能是System.nanoTime()的结果。
是否可以选择其他与这两个数字一样有效的数字?
并非每个数字都一样“好”。所以不行。
JRE的不同版本和实现之间的默认播种模式有所不同。
public Random() { this(System.currentTimeMillis()); }
public Random() { this(++seedUniquifier + System.nanoTime()); }
public Random() { this(seedUniquifier() ^ System.nanoTime()); }
如果您连续创建多个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的用法,而无需添加,无需异或,只需一个乘法即可。
上面提到的论文给出了c = 0和m = 2 ^ 64的良好“乘数”列表,如1181783497276652981。
总而言之:A努力@ JRE-developers;)但是有一个错字。(但谁知道,除非有人对其进行评估,否则丢失的前导1实际上可能会改善播种RNG。)
但是某些乘数肯定更糟:“ 1”导致序列恒定。“ 2”导致单比特移动序列(以某种方式相关)…
RNG的序列间相关实际上与(Monte
Carlo)模拟有关,在该模拟中,多个随机序列被实例化甚至并行化。因此,良好的播种策略对于获得“独立”仿真运行是必要的。因此,C ++
11标准引入了用于生成不相关种子的种子序列的概念。
例如下面的代码。它有一个随机类。然而,它总是在任何地方产生相同的输出。在这种情况下,哪一项是种子? 来源:link
什么是树上随机游走?我们可以假设给定一棵树,树的某个结点上有一个硬币,在某一时刻硬币会等概率地移动到邻接结点上,问硬币移动到邻接结点上的期望距离。 1. 树上随机游走用到的定义: ● 所讨论的树 ● 结点的度数 ● 结点与 v 结点之间的边的边权 ● 结点的父结点 ● 结点的子结点集合 ● 结点的兄弟结点集合 2. 向父结点走的期望距离 设代表 u 结点走到其父结点的期望距离,则有: 分
问题内容: 当他每次运行程序时都不断获得相同的数字时,我试图向Java解释随机数生成器。我为同一件事创建了自己的简单版本,每次运行该程序时,我也得到了与他得到的确切数字相同的数字。 我究竟做错了什么? 100个数字中的最后五个数字是: 问题答案: 您已经为随机数生成器提供了恒定的值。它是确定性的,因此每次运行都会生成相同的值。 我不确定您为什么选择使用作为种子,但是种子值与生成的值范围无关(这是由
一个简单的新手问题,奇怪的是我一直没能找到解决方法。
问题内容: 我正在尝试在Java中生成盐,以与用于安全密码存储的哈希算法配合使用。我正在使用以下代码创建随机盐: 这应该生成一个完全安全的,随机生成的盐,以用于我的哈希算法。但是,当我运行代码时,每次都会输出相同的盐…表示生成的盐根本不是随机的。 出于明显的安全性目的,每个用户都需要一个唯一的符号,但是如果我每次创建一个新帐户时都使用此代码,则每个用户都将具有相同的符号,这一开始就破坏了它的用途。
我正在尝试模拟我在上面发现的数学难题http://blog.xkcd.com/2010/02/09/math-puzzle/.然而,java random类返回了奇怪的结果。在下面的代码中,结果是预期的。第一行的输出大约为.612,第二行的输出介于.49和.51之间。int试验=10000000;int成功=0; 然而,当我切换 到 第一个数字的输出约为 .476,第二个数字的输出约为 .710。