为什么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 …
Run Code Online (Sandbox Code Playgroud) 两点 - 首先,示例是在Fortran中,但我认为它应该适用于任何语言; 第二,内置的随机数生成器并不是真正随机的,而且存在其他生成器,但我们对于将它们用于我们正在做的事情并不感兴趣.
关于随机种子的大多数讨论都承认,如果程序在运行时没有播种,那么种子将在编译时生成.因此,每次运行程序时都会生成相同的数字序列,这对随机数不利.克服这个问题的一种方法是使用系统时钟为随机数发生器播种.
但是,当在多核机器上与MPI并行运行时,我们的系统时钟方法产生了同样的问题.当序列从运行变为运行时,所有处理器都获得相同的系统时钟,因此具有相同的随机种子和相同的序列.
请考虑以下示例代码:
PROGRAM clock_test
IMPLICIT NONE
INCLUDE "mpif.h"
INTEGER :: ierr, rank, clock, i, n, method
INTEGER, DIMENSION(:), ALLOCATABLE :: seed
REAL(KIND=8) :: random
INTEGER, PARAMETER :: OLD_METHOD = 0, &
NEW_METHOD = 1
CALL MPI_INIT(ierr)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
CALL RANDOM_SEED(SIZE=n)
ALLOCATE(seed(n))
DO method = 0, 1
SELECT CASE (method)
CASE (OLD_METHOD)
CALL SYSTEM_CLOCK(COUNT=clock)
seed = clock + 37 * (/ (i - 1, i = 1, n) /)
CALL RANDOM_SEED(put=seed)
CALL RANDOM_NUMBER(random)
WRITE(*,*) …
Run Code Online (Sandbox Code Playgroud) 对于科学实验,我需要生成 10 个随机、固定大小的列表子集。为了使实验可重复,我想用已知种子初始化 10 个不同的 random.Random() 实例。
随机种子需要有多不同?似乎表明使用种子 1 到 10 可能是一个坏主意,因为结果可能是线性相关的。
如果在这种情况下选择种子 1 到 10 是不好的做法,那么以可重复的方式选择种子的好策略是什么?
澄清:在程序运行时(使用特定数据集)始终使用相同的种子是很重要的!最后,我的程序必须是确定性的。
我已经将我遇到的一个错误简化为以下几行代码:
int[] vals = new int[8];
for (int i = 0; i < 1500; i++)
vals[new Random(i).nextInt(8)]++;
System.out.println(Arrays.toString(vals));
Run Code Online (Sandbox Code Playgroud)
输出为:[0,0,0,0,0,1310,190,0]
这只是选择连续数字来种子随机然后使用功率为2的nextInt的工件吗?如果是这样,我是否应该注意到这样的其他陷阱,如果没有,我做错了什么?(我不是在寻找上述问题的解决方案,只是对其他可能出错的一些理解)
丹,写得很好的分析.由于javadoc非常清楚如何计算数字,所以为什么会发生这种情况并不是一个谜,就像还有其他类似的异常需要注意 - 我没有看到任何关于连续种子的文档,而我我希望有一些java.util.Random经验的人可以指出其他常见的陷阱.
至于代码,需要几个并行代理具有可重复的随机行为,这些行为恰好从枚举8个元素中选择,只要它们的第一步.一旦我发现了这种行为,种子都来自一个从已知种子创建的主随机对象.在程序的前一个(顺序播种)版本中,所有行为在第一次调用nextInt后迅速分散,因此我花了很长时间才将程序的行为缩小到RNG库,我想避免未来的情况.