如何获取Random.nextLong可返回的所有可能值?
How to obtain all possible values returnable by Random.nextLong?
Random#nextLong() 文档声明此方法不会 return 所有可能的 long
值:
Returns 来自该随机数生成器序列的下一个伪随机、均匀分布的 long 值。 nextLong
的一般契约是伪随机生成一个 long 值并 returned。方法 nextLong
由 class Random 实现,就好像通过:
public long nextLong() {
return ((long) next(32) << 32) + next(32);
}
因为class随机使用只有48位的种子,这个算法不会return所有可能的长值。
例如,数字 8090327796378429294
是可生成的,但数字 8090327796378429295
不是,即使它们的唯一区别是一个最低有效位,并且值本身是 63 位长。
有一种方法可以使用以下算法知道 return 值是否可以被 nextLong()
编辑:
public class JavaRandom {
private static final long ADD = 0xBL;
private static final long MULT = 0x5DEECE66DL;
private static final long TWO16 = 1L << 16;
private static final long MASK_31 = (1L << 31) - 1;
private static final long MASK_32 = (1L << 32) - 1;
private static final long MASK_48 = (1L << 48) - 1;
public static boolean canBeGeneratedByJavaRandom(long randomValue) {
long i1 = (randomValue >> 32) & MASK_32;
long i2 = (randomValue & MASK_32);
if (i2 > MASK_31) {
i1 = i1 + 1;
}
long front = i1 << 16;
for (long i = 0; i < TWO16; i++) {
long seed = front | i;
long i22 = (((seed * MULT) + ADD) & MASK_48) >> 16;
if (i22 == i2) {
return true;
}
}
return false;
}
}
如何在不对每个可能的 64 位数字进行 运行 检查的情况下获取 nextLong()
可以生成的所有值?在收集所有值之前调用 nextLong()
感觉不合理,而且可能会发生冲突。
鉴于 setSeed
函数完全使用传入值的低 48 位来设置种子,您可以简单地迭代所有 seed
值从 0
到 (1L << 48) - 1
, setSeed
给每个种子,然后为每个种子调用 nextLong()
一次。
更多信息:
- This answer 指出可以从 2 个连续的
nextInt()
值确定种子,因此没有两个不同的种子会生成相同的 2 个连续的 nextInt()
值。
- 文档指出
nextInt()
调用 next(32)
,nextLong()
获取 2 个连续 next(32)
值的值。
从以上两点来看,不同的种子值会产生不同的nextLong()
值。
Random#nextLong() 文档声明此方法不会 return 所有可能的 long
值:
Returns 来自该随机数生成器序列的下一个伪随机、均匀分布的 long 值。 nextLong
的一般契约是伪随机生成一个 long 值并 returned。方法 nextLong
由 class Random 实现,就好像通过:
public long nextLong() {
return ((long) next(32) << 32) + next(32);
}
因为class随机使用只有48位的种子,这个算法不会return所有可能的长值。
例如,数字 8090327796378429294
是可生成的,但数字 8090327796378429295
不是,即使它们的唯一区别是一个最低有效位,并且值本身是 63 位长。
有一种方法可以使用以下算法知道 return 值是否可以被 nextLong()
编辑:
public class JavaRandom {
private static final long ADD = 0xBL;
private static final long MULT = 0x5DEECE66DL;
private static final long TWO16 = 1L << 16;
private static final long MASK_31 = (1L << 31) - 1;
private static final long MASK_32 = (1L << 32) - 1;
private static final long MASK_48 = (1L << 48) - 1;
public static boolean canBeGeneratedByJavaRandom(long randomValue) {
long i1 = (randomValue >> 32) & MASK_32;
long i2 = (randomValue & MASK_32);
if (i2 > MASK_31) {
i1 = i1 + 1;
}
long front = i1 << 16;
for (long i = 0; i < TWO16; i++) {
long seed = front | i;
long i22 = (((seed * MULT) + ADD) & MASK_48) >> 16;
if (i22 == i2) {
return true;
}
}
return false;
}
}
如何在不对每个可能的 64 位数字进行 运行 检查的情况下获取 nextLong()
可以生成的所有值?在收集所有值之前调用 nextLong()
感觉不合理,而且可能会发生冲突。
鉴于 setSeed
函数完全使用传入值的低 48 位来设置种子,您可以简单地迭代所有 seed
值从 0
到 (1L << 48) - 1
, setSeed
给每个种子,然后为每个种子调用 nextLong()
一次。
更多信息:
- This answer 指出可以从 2 个连续的
nextInt()
值确定种子,因此没有两个不同的种子会生成相同的 2 个连续的nextInt()
值。 - 文档指出
nextInt()
调用next(32)
,nextLong()
获取 2 个连续next(32)
值的值。
从以上两点来看,不同的种子值会产生不同的nextLong()
值。