【问题标题】:Why does rand from stdlib not follow law of large numbers?为什么标准库中的 rand 不遵循大数定律?
【发布时间】:2015-04-09 15:02:44
【问题描述】:

在下面的代码中,我预计一个骰子会扮演数十亿次的角色,平均结果正好是 3.5,高于 3.5 的百分比有时是 5%,而其他时候(当然有不同的种子)是就像 95。但即使你达到 6040M 的高度,你也永远不会超过 50%,低于 3.5 的 50%?显然 rand() 有一点偏差...

我知道“真正的随机”并不存在,但它真的这么明显吗?

典型的输出是:

平均:3.50003 计数器:3427000000 百分比高于:83.2554 Perc abs 高于计数器:50.0011
平均:3.49999 计数器:1093000000 高于百分比:92.6983 Perc abs 高于计数器:50.0003

#include <stdio.h>      /* printf, scanf, puts, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */
#include <unistd.h>
#include <iostream>
using namespace std;

int main ()
{
  long long int this_nr;
  long long int counter = 0;
  long long int above_counter = 0;
  long long int below_counter = 0;
  long long int above_counter_this = 0;
  long long int below_counter_this = 0;

  long long int interval_counter = 0;

  double avg = 0.0;
  srand (time(NULL));
  srand (time(NULL));
  srand (time(NULL));
  cout.precision(6);

  while(1) {
      this_nr = rand() % 6 + 1; // 0,1,2,3,4,5 or 6
      avg = ((double) this_nr + ((double)counter * (double) avg))
          / ((double) counter+1.0);
      if (this_nr <= 3) below_counter_this++;
      if (this_nr >= 4) above_counter_this++;
      if (avg < 3.5) below_counter++;
      if (avg > 3.5) above_counter++;
      if (interval_counter >= 1000000) {
        cout << "Average: " << avg << " counter: " << counter << " Percentage above: "
                 << (double) above_counter / (double) counter * 100.0
                 << " Perc abs above counter: " << 100.0 * above_counter_this / counter
                 << "                 \r";
        interval_counter = 0;
      }
      //usleep(1);
      counter++; 
      interval_counter++;
  }
}

【问题讨论】:

  • 请注意所有投掷的平均值与高于 3.5 的投掷百分比之间的差异。我担心平均值,永远不会达到 50% 左右
  • this_nr = rand() % 6 + 1; // 0,1,2,3,4,5 or 6 没有正确描述输出。使用代码中的+ 1,输出0 是不可能的。您可能的输出是:仅 1、2、3、4、5、6。
  • 你说的很对。不过,评论是错误的部分。我的期望确实是 1、2、3、4、5 或 6。谢谢!
  • 顺便说一句,您确实意识到多个 srand() 毫无意义?至少它们在循环之外是正确的——我们必须每周至少修复一次该错误。此外,当您将 interval_counter 归零时,您似乎并未将所有统计信息归零。例如, above_counter 和 below_counter 似乎在不断累积,因此您的试验不是独立的。
  • 独立试验...我怎么会忘记:)

标签: c++ random std average


【解决方案1】:

rand() 众所周知是一个糟糕的生成器,它在低位特别糟糕。执行% 6 只会删除低位。您也有可能遇到一些modulo bias,但我预计这种影响相对较小。

【讨论】:

  • 感谢您的意见。你或有人有更好的建议吗?在C中,最好
  • 当我将种子放入循环中时,偏差会变大,但平均进度不会超过 50-50%
  • 永远不要继续重新播种生成器!播种一次,然后使用。
  • 要获得更好的生成器,请查看您的系统上是否有 random。这有点好,但不是很好。如果您使用的是 OS X,则可以使用 arc4random,这非常好。另一种选择是查找并下载 Mersenne Twister 的 C 实现。
  • 好的,所以这里最好的答案是发电机的质量?谢谢..我在 PHP 中尝试过这个,并且似乎得到了较小的偏见 btw...
猜你喜欢
  • 2017-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 2010-10-08
  • 1970-01-01
  • 2010-10-06
  • 1970-01-01
相关资源
最近更新 更多