【问题标题】:How does bias manifest in bounded random number generation偏差如何在有界随机数生成中表现出来
【发布时间】:2020-04-08 18:49:56
【问题描述】:

我正在尝试消化以下帖子 https://www.pcg-random.org/posts/bounded-rands.html 关于无偏见、高效的随机数生成。

这是描述经典模数方法的摘录。

uint32_t bounded_rand(rng_t& rng, uint32_t range) {
    return rng() % range;
}

但除了慢之外,还有偏颇。了解为什么 rand() % 52 产生有偏差的数字,如果我们假设 rand() 产生 [0..2^32) 范围内的数字,观察到 52 并不完美 除以 2^32,它将它除以 82,595,524 次,余数为 48。含义 如果我们使用 rand() % 52,将有 82,595,525 种选择方式 我们 52 张牌中的前 48 张牌,只有 82,595,524 种方式 选择最后四张牌。换句话说,有一个 0.00000121% 对最后四张牌的偏见......

这篇文章继续展示了另一种技术,该技术使用浮点算法从本质上生成所需范围的随机分数并将其截断为整数。

static uint32_t bounded_rand(rng_t& rng, uint32_t range) {
    double zeroone = 0x1.0p-32 * rng();
    return range * zeroone;
}

这种方法与经典的模方法一样有偏见,但是 偏见以不同的方式表现出来。例如,如果我们是 选择 [0..52) 范围内的数字,数字 0、13、26 和 39 会比其他人少出现一次。

最后一段让我感到困惑。我不太精通浮点算术,所以我很难在取模方法中的偏差和浮点方法中的偏差之间建立联系。我所看到的是,在这两种技术中,有 4 个数字是有偏见的。

【问题讨论】:

    标签: random


    【解决方案1】:

    让我们从小事做起。假设我们有一个方法 rng() 可以在 [0, 128) 中生成任何随机整数。如果我们将其所有 128 个结果映射如下(其中 X 是这些结果之一):

     floor((X / 128.0) * 52)
    

    然后我们得到下表:

     0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21, 21, 22, 22, 23, 23, 23, 24, 24, 25, 25, 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, 30, 30, 30, 31, 31, 32, 32, 32, 33, 33, 34, 34, 34, 35, 35, 36, 36, 36, 37, 37, 38, 38, 39, 39, 39, 40, 40, 41, 41, 41, 42, 42, 43, 43, 43, 44, 44, 45, 45, 45, 46, 46, 47, 47, 47, 48, 48, 49, 49, 49, 50, 50, 51, 51
    

    请注意,有些数字在此表中出现了两次,有些则出现了 3 次。这是因为我们将一个大范围映射到一个小范围,而 128 不能被 52 整除,而且还因为舍入误差。在这个例子中,52 除以 128 大约是 0.4,所以表中的下一个条目是前一个条目加上大约 0.4,然后表中的所有条目都向下舍入,从而产生一些比其他更频繁出现的数字。另一方面,如果我们使用 64 而不是 52,那么 128 项表中的所有 64 个条目将恰好出现两次。

    另见 Daniel Lemire 的“A Fast Alternative to the Modulo Reduction”。


    这是上面表格的详细形成方式。如果我们将这些结果映射如下:

    X / 128.0
    

    那么表格的开头将如下所示:

    0.000, 0.008, 0.016, 0.023, 0.031, 0.039, 0.047, 0.055, 0.062, 0.070, 0.078, 0.086, 0.094, 0.102, 0.109, 0.117, 0.125, 0.133, ...
    

    如果我们将此表乘以 52,它现在看起来像:

    0.000, 0.406, 0.812, 1.219, 1.625, 2.031, 2.438, 2.844, 3.250, 3.656, 4.062, 4.469, 4.875, 5.281, 5.688, 6.094, 6.500, 6.906, 7.312, ...
    

    最后我们四舍五入得到:

    0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-31
      • 2013-07-29
      • 2012-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多