这是我的代码,用一个种子作为参数来生成随机数:
double randomGenerator(long seed) {
Random generator = new Random(seed);
double num = generator.nextDouble() * (0.5);
return num;
}
每次我给出一个种子并尝试生成100个数字时,它们都是相同的。
我该如何解决这个问题?
伪随机数生成器(PRNG),也称为确定性随机位生成器DRBG,是一种算法,用于生成近似于随机数属性的数字序列。该序列在本质上不是真正的随机数,因为它完全由一个相对较小的初始值集合(称为PRNG的状态,其中包括真正的随机种子)确定。如果您想要不同的序列(通常情况下,不调整或调试算法时),应该调用零参数构造函数,该构造函数使用nanoTime尝试每次获得不同的种子。当然,这个
Random
实例应该在您的方法之外保留。private Random generator = new Random();
double randomGenerator() {
return generator.nextDouble()*0.5;
}
public Random() {
this(seedUniquifier() ^ System.nanoTime());
}
- dermoritz简单的方法是使用:
Random rand = new Random(System.currentTimeMillis());
这是生成随机
数的最佳方式。
你不应该在方法范围内创建新的Random。将其设置为类成员:
public class Foo {
private Random random
public Foo() {
this(System.currentTimeMillis());
}
public Foo(long seed) {
this.random = new Random(seed);
}
public synchronized double getNext() {
return generator.nextDouble();
}
}
这只是一个例子。我认为以这种方式包装Random
没有任何价值。可以将其放入使用它的类中。
nextDouble
总是返回随机序列中的 第一个 双精度浮点数。而这个答案只会创建一次随机数生成器,每次调用 getNext
时会逐步遍历随机数序列并返回不同的数值。 - Brandon这就是伪随机数生成器的原理。这些数字并不真正随机,它们是通过一个确定性算法生成的,但是根据不同的种子,生成的数字序列会有所不同。由于你总是使用相同的种子,因此你总是得到相同的序列。
Random
实例,但这是不必要的。也没有理由像某个解决方案那样使用synchronized
。相反,应该利用ThreadLocalRandom
类上的方法:double randomGenerator() {
return ThreadLocalRandom.current().nextDouble(0.5);
}
例如:
public double[] GenerateNumbers(long seed, int amount) {
double[] randomList = new double[amount];
for (int i=0;i<amount;i++) {
Random generator = new Random(seed);
randomList[i] = Math.abs((double) (generator.nextLong() % 0.001) * 10000);
seed--;
}
return randomList;
}
如果您使用相同的种子,它将显示相同的列表。
System.currentTimeMillis()
作为随机数生成器的种子来生成随机结果。不提供种子也会产生随机结果。如果不提供种子,我不确定随机数生成器是否会在某个时候开始重复。 - WVrock