【问题标题】:Random Number Generator with Modulo带模的随机数生成器
【发布时间】:2014-02-05 18:56:39
【问题描述】:

我尝试了一个使用 C++ 随机数生成器代码的小实验。我把代码贴出来给大家看看。

unsigned int array[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned int rand_seed = 4567;
int loop = 0;

 srandom(rand_seed);
 while (loop < 2147483647)
 {
     array[random() % 10]++;
     loop++;
 }

 for (int i = 0; i < 10; i++)
 {
     cout << array[i] << endl;
 }

这是一个简单的代码,这里不多解释。我了解到模运算会导致小偏差,在这种情况下,0 的出现应该高于其他值,因为 0 本身被计算在内,并且每当出现 10 时。但是当我显示我的array 的内容时,0 到 9(含)之间的所有数字的值几乎相同。

谁能告诉我这个偏见实际上是正确的还是不正确的?如果是,模运算确实会引入偏差,为什么我看不到呢?

用数学术语来说,我可以说我的随机变量 X 可以有 0 到 9(含)之间的确定值,并且通过绘制频率值(基本上是 array 值),结果图是一个概率密度函数。

只是为了让问题完整,我在array 中得到的结果。

214765115
214745521
214749449
214749304
214747088
214733986
214745858
214743477
214760340
214743509

【问题讨论】:

  • 所提供的所有答案都得到了很好的解释,因此我赞成对所有答案进行投票。可悲的是,我只能选择一个来关闭线程。

标签: c++ math random statistics probability


【解决方案1】:

这是一个简单的代码,这里不多解释。我学会了模 操作会导致小偏差,在这种情况下应出现 0 高于其他值,因为 0 本身被计算在内,每当 10 发生。

不仅是 10,而且所有其他数字也将包含在 [0,9] 之间,因为取模是用 10 作为除数完成的。所以这里有一个从 random() 返回的值(即假设 [0,255],POSIX random() 范围更广,但这个想法很重要)到域 [0,9] 的映射。这会引入偏见。

用数学术语,我可以说我的随机变量 X 可以有确定的 0 到 9(含)之间的值并通过绘制频率值 (本质上是数组值),结果图是一个概率 密度函数。

这绝对是一个分布,但是这在范围 [0,9] 上并不均匀,而是向左倾斜。在我们的例子中,有 n=256 种可能性,这里是一个概率密度函数

x f(x)
0 26/256
1 26/256
2 26/256
3 26/256
4 26/256
5 26/256
6 25/256
7 25/256
8 25/256
9 25/256
sum   1

【讨论】:

  • random() 真的返回[0,255] 范围内的值吗? (就此而言,random() 是什么?我知道在一些早期的 Unix 上有一个同名的函数,但我今天找不到任何关于它的信息。)
  • random(),一个 POSIX 标准,范围更广,但同样会出现偏差
【解决方案2】:

随着模数的增加,偏差会变大,随着最大随机数的增加,偏差会变小。在这种情况下,10 与最大的随机数相比非常小,因此偏差几乎无法测量。

如果您想查看更好的示例,请使用更少的随机数返回位。

int random_value = random() & 0xfff;
array[random_value % 10]++;

【讨论】:

  • 我们怎样才能避免这种偏见?
  • @Psypher 避免使用数值计算的东西,使用已经为您消除它的代码,即 C++11 兼容实现中提供的 &lt;random&gt; 库。特定于那个std::uniform_int_distribution&lt;&gt;。老实说,图书馆非常出色。如果可能的话,使用它并避免rand() 像瘟疫一样。
  • 否则你会被困在选择一个平均划分初始范围的模数,然后执行一个draw-and-discard算法。
  • @DavidO 大多数好的生成器都有一个质数范围,这使得选择该模数变得困难。通常的解决方案是找到小于或等于生成器返回的最大值,并且可以被区间整除的最大值,并丢弃高于它的值。
  • @Psypher 避免偏差的唯一方法是确保输入范围是输出范围的整数倍。通常的方法是丢弃大于该整数倍的随机数。假设随机数在 0 和 2147483647 之间产生,并且您取模 10,这意味着丢弃任何 >= 2147483640 的东西。这应该只会在 2147483648 中出现 7 次,因此不会对性能造成很大影响。附言看到偏见的几率是一样的。
【解决方案3】:

例如,假设random 返回一个unsigned char 所以值在[0; 255] 之间

现在如果我们使用modulo % 10,由于[250; 255],我们将拥有更多0, 1, 2, 3, 4, 5

【讨论】:

  • 我该如何测试这个。我总是返回一个介于02^31 - 1 之间的随机函数。还有一件事,当我绘制频率时,它是概率密度函数吗?
猜你喜欢
  • 1970-01-01
  • 2015-12-06
  • 1970-01-01
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
  • 2020-03-14
  • 1970-01-01
相关资源
最近更新 更多