关于将long
提供给种子java.util.Random
,如果我将对象实例化一次,似乎我只是把时间当作种子,这对于程序的生命是令人满意的,出于我的目的,意味着对nextDouble()
的一系列调用的结果看起来是随机的。
假设代码简单的原因,我实例化Random
,多次使用它,然后重新实例化,并重复。如果种子类似地提供,则种子将是相似的并且增加,因为它基于时间。如果它是自1970年1月1日以来的秒数,则增加量将小于该值。(编辑:此问题在2011年被提出。)
如果我链接nextDouble()
的输出,那么使用非随机的基于时间的种子重新实例化Random
会导致一个微妙的模式出现在{{1的输出的复合链中}}。另一种表达这个问题的方法是:我是否需要从nextDouble()
的集合中统一绘制种子。
答案 0 :(得分:7)
你可能会遇到这样的情况,确实会给他们分配相同的种子,特别是如果它们是在同一毫秒内创建的。有些机器的分辨率低至15毫秒或更高,因此它成为一个更大的问题。
解决此问题的一种方法是使用Math.random()
。它使用一个系统范围的随机实例,它只在第一次使用时才被实例化。我不相信你有权访问底层实例,所以你不能用它来获取nextInt()
,但你可以使用Math.random()
获得双打,或者如果你真的想要自己的Random对象,那么来自double
的{{1}},将其位转换为Math.random()
,并使用long
作为新long
的种子。
可以找到随机的Oracle文档here。
Random
答案 1 :(得分:4)
自动生成的随机种子使用System.nanoTime和计数器来确保它始终不同。恕我直言,没有必要使用种子来改善随机性
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;
}
}
Random使用48位种子并重复每2 ^ 48个调用,这意味着它无法生成每个可能的long
或double
值。
与种子混淆听起来有点像三重随机策略,实际上并没有帮助。 http://thedailywtf.com/Articles/Random-Char-and-TriplyRandom-Double.aspx
如果您想要更大的随机性,请使用SecureRandom,即使您每次都给它1个种子,它也不会提供相同的随机序列。这可以产生每个可能的long
和double
值。
答案 2 :(得分:2)
当然,这取决于生成器,但根据我的经验,对种子的微小更改会对生成的值产生很大影响。
可能通过一些工作可以检测到,但除非你正在进行高端统计工作或加密,否则它不会产生一些差别。
在任何情况下,如果 在该类型的域中,您将使用基于硬件的随机数生成,很可能使用类似3开尔文背景辐射的来源: - )< / p>