java.util.Random NextDouble()偏向于更高的统一数

时间:2015-04-30 15:30:34

标签: java random

我使用NextDouble()生成统一的随机数。我用500个不同的种子生成随机数,发现生成的均匀随机数偏向更高的统一数(平均值为0.93)。这是非常荒谬的。然后我将种子除以10000,产生的随机数是完美的(平均值为0.51)。 我发现种子不应该超过48位,因此确保我提供的种子(NextDouble()的种子是随机生成的nextLong(),种子= 12345)少于48位。然后我重新生成了500次随机数,发现了同样的问题。是否有人与NextDouble()有类似的问题?

请参阅以下代码:

Random randObject = new Random();

randObject.setSeed(12345);

long[] seed = new long[501];
for (int i = 1; i<=500; i++)
seed[i] = (long)( ( randObject.nextLong() / (double)Long.MAX_VALUE ) * Math.pow( 2, 48 ) ); // to make sure seed is not more than 48 bits

for (int i = 1; i<=500; i++)
{
  randObject.setSeed(seed[i]);
  randObject.nextDouble();
}

由于

3 个答案:

答案 0 :(得分:0)

恭喜

  

我发现种子不应超过48位,因此确保我提供的种子(NextDouble()的种子是使用seed = 12345的nextLong()随机生成的,少于48位。

您通过实验证明java.util.Random是48位LCG生成器

从其来源

48: * The algorithm is described in <em>The Art of Computer Programming, 49: * Volume 2</em> by Donald Knuth in Section 3.2.1. It is a 48-bit seed, 50: * linear congruential formula. 51: *

链接http://developer.classpath.org/doc/java/util/Random-source.html

答案 1 :(得分:0)

Java Randomlinear congruential generator (LCG),它从当前状态传播下一个状态。您正在使用LCG的输出来自行播种,因此您的每个种子都将与其他种子产生的输出相关联。从那时起,关于结果的分布行为,所有的赌注都是关闭的。

/dev/random为您的500个流播种,或者使用完全不同类别的生成器(例如feedback shift registerMersenne twister)的输出。然后,如果您仍然在观察偏见,请写一份期刊论文。

答案 2 :(得分:0)

Java-8版本似乎提供了不同的图片:

public void test() {
    Random r1 = new Random();
    Random r2 = new Random();

    r1.setSeed(12345);
    double average = IntStream.range(0, 5000)
            // 5000 random longs.
            .mapToLong(i -> r1.nextLong())
            // Used as seeds to a Random
            .mapToDouble(l -> {
                r2.setSeed(l);
                return r2.nextDouble();
            })
            // Gather stats.
            .summaryStatistics()
            // Average,
            .getAverage();
    System.out.println("Average: " + average);
}

相当一致地打印0.5000...