【问题标题】:3 random numbers from 2 random numbers task来自 2 个随机数任务的 3 个随机数
【发布时间】:2016-06-02 09:58:06
【问题描述】:

假设,你有一些统一的分布 rnd(x) 函数会返回 0 或 1。 您如何使用此函数创建任何 rnd(x,n) 函数将返回从 0 到 n 的均匀分布数?

我的意思是每个人都在使用它,但对我来说它并不那么聪明。例如,我可以创建右边界为 2^n-1([0-1]、[0-3]、[0-7] 等)的分布,但找不到如何为范围执行此操作的方法像 [0-2] 或 [0-5] 不使用非常大的数字以获得合理的精度。

【问题讨论】:

  • 检查算术编码;基本上 AC 将输入视为一个非常大的数字,但每个码字都可以从相当小的比特邻域中解码。

标签: math probability probability-theory


【解决方案1】:

假设您需要使用另一个返回 0 或 1 的函数 rnd1() 创建返回范围 [0, n] 内均匀分布的随机数的函数 rnd(n)

  1. 找到最小的k2^k >= n+1
  2. 创建由k 位组成的数字,并使用rnd1() 填充其所有位。结果是 [0, 2^k-1] 范围内的均匀分布数
  3. 将生成的数字与n 进行比较。如果它小于或等于 n,则返回它。否则转到第 2 步。

一般来说,这是如何使用生成大范围数字的库函数在小范围内生成统一数字的一种变体:

unsigned int rnd(n) {
  while (true) {
    unsigned int x = rnd_full_unsigned_int();
    if (x < MAX_UNSIGNED_INT / (n+1) * (n+1)) {
      return x % (n+1);
    }
  }
}

上面代码的解释。如果您只是返回rnd_full_unsigned_int() % (n+1),那么这将产生对小值数字的偏见。黑色螺旋代表从 0 到 MAX_UNSIGNED_INT 的所有可能值,从内部计数。单转路径长度为(n+1)。红线显示了为什么会出现偏差。因此,为了消除这种偏差,我们首先在 [0, MAX_UNSIGNED_INT] 范围内创建随机数 x(这很容易使用位填充)。然后,如果 x 落入偏差生成区域,我们重新创建它。我们不断地重新创建它,直到它不落入产生偏差的区域。 x此时的形式为a*(n+1)-1,所以x % (n+1)是一个均匀分布的数[0, n]。

【讨论】:

  • 我不确定结果是否会均匀分布。你能解释一下为什么会这样吗?我真的很感激。
  • 随机数在 0..2^k-1 范围内是统一的,因此在任何子范围内也是统一的,例如[m .. 2^k - n];缺点是当 'n' 或 'm' 很大时,必须丢弃许多(所有)位的随机数据。
  • 谢谢,现在我明白了!顺便说一句,有没有办法更有效地做到这一点?我的意思是,失败的可能性是 1-n/(2^ceil(log2(n))),有时几乎是 50%。
猜你喜欢
  • 1970-01-01
  • 2019-05-24
  • 2014-02-11
  • 2011-06-14
  • 1970-01-01
  • 2012-08-12
  • 2018-11-06
  • 2013-10-05
  • 2015-01-22
相关资源
最近更新 更多