0

我正在使用 java 6 random (java.util.Random,linux 64) 随机决定在提供页面的一个版本到第二个版本之间进行随机决定(普通 A/B 测试),从技术上讲,我使用默认的空构造函数初始化该类一次并将其作为属性注入到 bean (Spring) 中。大多数情况下,页面的副本彼此之间的误差在 8%(+-) 以内,但有时我会看到高达 20% 的偏差,例如:

我现在有两个分开的副本:680 / 570 被认为是正常的吗?有没有比 java random 更好/更快的版本?

谢谢

4

3 回答 3

3

20% 的偏差确实看起来相当大,但您需要与训练有素的统计学家交谈,以确定它是否在统计上异常。

更新- 答案是它不一定是异常的。统计数据预测,大约 0.3% 的时间会出现这样的异常值。


随机数生成器导致这样的结果当然是合理的。该类Random使用简单的“线性同余”算法,并且此类算法具有强自相关性。根据您使用随机数的方式,这可能会导致应用程序级别的异常。

如果这是您的问题的原因,那么您可以尝试用加密强度随机数生成器替换它。请参阅 .java 文档SecureRandomSecureRandom比 贵Random,但这不太可能对您的用例产生任何影响。


另一方面,如果这些异常值实际上以理论预测的大致速度发生,那么更改随机数生成器应该不会产生任何影响。

如果这些异常值真的很麻烦,那么你需要采取不同的方法。与其生成 N 个随机选择,不如生成一个完全符合所需比率的 false/true 列表,然后将列表打乱;例如使用Collections.shuffle.

于 2012-10-24T15:11:48.747 回答
0

java.util.Random.nextBoolean() 是标准二项分布的一种方法,其标准差为 sqrt(n*p*(1-p)),p=0.5。

因此,如果您进行 900 次迭代,则标准差为 sqrt(900*.5*.5) = 15,因此大多数情况下分布在 435 - 465 范围内。

然而,它是伪随机的,并且在重新开始之前它会经历一个有限的数字循环。因此,如果您有足够的迭代次数,实际偏差将比理论偏差小得多。Java 使用公式种子 = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)。您可以使用较小的数字编写一个不同的公式来故意获得较小的偏差,这将使其成为更差的随机数生成器,但更适合您的目的。

例如,您可以在其中创建一个包含 5 个真和 5 个假的列表,并使用 Collections.shuffle 来随机化该列表。然后你依次迭代它们。10 次迭代后,您重新排列列表并从头开始。这样你的偏差永远不会超过 5。

有关数学,请参见http://en.wikipedia.org/wiki/Linear_congruential_generator

于 2012-10-24T15:56:49.680 回答
0

我相信这是相当正常的,因为它是为了生成随机序列。如果您想要在一定间隔后重复模式,我认为您可能希望在构造函数中使用特定seed值并在一定间隔后使用相同的种子重置随机数。

例如,在每 100/500/n 次调用后Random.next..,使用方法重置具有旧值的种子Random.setSeed(long seed)

于 2012-10-24T15:10:20.730 回答