随机均匀分布

15

我知道如果我使用Java中的随机生成器,使用nextInt生成数字,那么这些数字将是均匀分布的。但是如果我使用两个Random实例,使用这两个Random类生成数字,这些数字是否仍然是均匀分布的呢?

2个回答

9
每个Random实例生成的数字都是均匀分布的,因此,如果将两个Random实例生成的随机数序列组合起来,它们也应该是均匀分布的。
请注意,即使结果分布是均匀的,您可能仍需要注意种子,以避免两个生成器的输出之间存在相关性。如果使用默认的无参构造函数,则种子应该已经不同。从java.util.Random的源代码中可以看到:
private static volatile long seedUniquifier = 8682522807148012L;

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

如果您通过使用Random(long seed)构造函数或调用setSeed(long seed)来显式设置种子,则需要自行处理此问题。一个可能的方法是使用随机数生成器为所有其他生成器生成种子。


@J-16:我相信在Java 1.5引入的新Java内存模型中已经保证了这一点(http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile)。无论如何,这不是我的代码;它是`java.util.Random`的内部实现。 - Grodriguez
在任何JMM下,long都是原子的,无论你是否将其标记为volatile(这意味着您永远不会看到半写入的值)。但是不是原子的(再次无论volatile如何)是读取和增量和写入长整型变量。因此,多个线程都可以将变量读取为0(例如),所有线程都将该值增加到1,并且所有线程都将1写回变量。为确保每次访问计数器100%可靠地递增,您需要同步。java.util.concurrent.atomic中的类(如AtomicLong)使此过程变得简单且正确。 - Mike Clark
2
@Mike:错了。非易失性长整型的读写不保证原子性,你肯定会看到半写入的值。但是标记为“volatile”的长整型则不同。请参见Java语言规范第17.7节(http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.7)。此外,您可以通过简单的测试程序轻松检查此内容。尽管如此,您关于读取-修改-写入周期不以原子方式发生的评论是正确的。 - Grodriguez
System.nanoTime() 是单调递增的,你极不可能在同一纳秒内在两个线程中同时调用它。 - Peter Lawrey
1
@Peter:请注意,即使这两个调用不是在同一纳秒内发生的,也不能保证System.nanoTime()实际上会反映出这一点。从Javadoc中可以看到:“此方法提供纳秒精度,但不一定具有纳秒精度。对于值的更改频率没有任何保证。” - Grodriguez
显示剩余2条评论

9

如果您使用相同的值来初始化两个Random实例,那么您肯定不能获得高质量的离散均匀分布。考虑最基本的情况,它会打印出完全相同的数字两次(没有比这更不随机的了...):

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());
    }        
}

但这只是一个单次迭代。如果我们开始增加样本量会发生什么呢?
下面是散点图,显示了运行两个具有相同种子的 RNG 并排生成总共 2000 个数字的分布: alt text 这里是运行单个 RNG 以生成总共 2000 个数字的分布: alt text 很明显第一种方法在这个有限集合上产生了更高质量的离散均匀分布。
现在几乎每个人都知道使用相同的种子来初始化两个 RNG 是不好的,如果您正在寻找高质量的随机性。但是这种情况确实让你停下来思考:我们已经创造了一个场景,在这个场景中,每个 RNG 都独立地发出相当高质量的随机性,但当它们的输出组合在一起时,其质量明显降低(不够离散)。

1
你用问题回答问题。 - David Larochette
你是对的,但请注意,即使在这种情况下,结果分布也是均匀的。 - Grodriguez
1
@Grodriguez,这个图可能会误导人 - 请记住,在第一个散点图上,每个点实际上是两个完全重叠的点。从视觉上看,图表1似乎是均匀的,只是样本比图表2少。但实际上,两个图表都有相同数量的样本 - 第一个比第二个更随机地放置。至少,我是这么想的。我想知道卡方检验对输出会有什么说法。 - Mike Clark
是的,我知道。然而,结果分布仍然是均匀的。 - Grodriguez
我不是一名统计学家。我不知道正确的术语来描述 RNG1(s1) 和 RNG2(s1) 协同工作会产生比仅使用 RNG1(s1) 更低质量的离散均匀分布这一事实。 - Mike Clark
@MikeClark,这并不是因为它更不均匀,而只是样本较小。如果您使用1000个值而不是2000个值运行单个rng,则会得到相同的输出。 - shinzou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接