Uniform distribution with Random

2019-04-18 23:06发布

I know if i use the Random generator from Java, generating numbers with nextInt, the numbers will be uniformly distributed. But what happens if I use 2 instances of Random, generating numbers with the both Random classes. The numbers will be uniformly distributed or not?

标签: java random
2条回答
霸刀☆藐视天下
2楼-- · 2019-04-18 23:53

Well, if you seed both Random instances with the same value, you will definitely not get quality discrete uniform distribution. Consider the most basic case, which literally prints the exact same number twice (doesn't get much less random than that ...):

public class RngTest2 {
    public static void main(String[] args) throws Exception {
        long currentTime = System.currentTimeMillis();
        Random r1 = new Random(currentTime);
        Random r2 = new Random(currentTime);
        System.out.println(r1.nextInt());
        System.out.println(r2.nextInt());
    }        
}

But that's just a single iteration. What happens if we start cranking up the sample size?

Here is a scatter plot of a distribution from running two same-seeded RNGs side-by-side to generate 2000 numbers total:

alt text

And here is a distribution of running a single RNG to generate 2000 numbers total:

alt text

It seems pretty clear which approach produced higher quality discrete uniform distribution over this finite set.

Now almost everyone knows that seeding two RNGs with the same seed is a bad idea if you're looking for high quality randomness. But this case does make you stop and think: we have created a scenario where each RNG is independently emitting fairly high quality randomness, but when their output is combined it is notably lower in quality (less discrete.)

查看更多
在下西门庆
3楼-- · 2019-04-19 00:02

The numbers generated by each Random instance will be uniformly distributed, so if you combine the sequences of random numbers generated by both Random instances, they should be uniformly distributed too.

Note that even if the resulting distribution is uniform, you might want to pay attention to the seeds to avoid correlation between the output of the two generators. If you use the default no-arg constructor, the seeds should already be different. From the source code of java.util.Random:

private static volatile long seedUniquifier = 8682522807148012L;

public Random() { this(++seedUniquifier + System.nanoTime()); }

If you are setting the seed explicitly (by using the Random(long seed) constructor, or calling setSeed(long seed)), you'll need to take care of this yourself. One possible approach is to use a random number generator to produce the seeds for all other generators.

查看更多
登录 后发表回答