C ++生日概率

时间:2015-06-30 01:04:10

标签: c++

我正在努力教自己C ++为今年秋天的研究生院做准备,但我遇到了这个生日悖论问题。我的代码似乎运行正常,但我没有得到正确的输出。如果有人有任何建议,请告诉我。

 #include <cstdlib>
 #include <iostream>
 #include <ctime>

 using namespace std;

int main()
{
    srand(time(NULL));

    const int trials = 100000;
    int birthdays[50];
    int numMatches;


    for(int i = 2; i <= 50; i++)
    {
        numMatches = 0;

        for(int j = 1; j <= trials; j++)
        {

            for(int k = 1; k <= i; k++)
            {
                birthdays[k] = (rand() % 365) + 1;
            }

            int m = 1;
            bool matched = false;
            while(m < i && !matched){
                int n = m + 1;

            while(n <= i && !matched){
                if(birthdays[m] == birthdays[n]){
                    numMatches++;
                    matched = true;
                }
                n++;
            }
                m++;
            }
        }

        cout << "Probability of " << i << " people in a room sharing a birthday is \t"
          << ( float(numMatches) / float(trials) ) << endl;
    }  
}

4 个答案:

答案 0 :(得分:1)

您的代码不计算50人共享生日的两个人的概率。有几个错误,主要是索引,但这是最大的问题:

for(int j = 1; j <= trials; j++) {
    // assigns a random birthday to the first i people (should be 0 indexed)
    for(k = 1; k <= i; k++)
        birthdays[k] = (rand() % 365) + 1;
    // Does *exactly* the same thing as the previous loop, overwriting what
    // the initial loop did. Useless code
    for(m = 1; m <= i; m++)
        birthdays[m] = (rand() % 365) + 1;
    // At this point, m = k = i + 1. Here you check if
    // the i + 1st array value has the same b-day. It will, because they're
    // the same thing. Note you never set the i + 1st value so the loops
    // above did nothing
    if(birthdays[k] == birthdays[m])
        ++numMatches;
}

所以你在这里得到的是:

  • 执行以下48次迭代(从第一次循环开始,从2到50:不知道这些值来自哪里)
    • 对于这48次迭代中的每次迭代,执行10k次迭代:
      • 将一堆随机内容分配给数组覆盖内容
      • 忽略您在数组中写入的值,进行始终为真的比较并将numMatches增加1

答案 1 :(得分:0)

我认为代码必须是这样的。

#include <cstdlib>
#include <iostream>
#include <ctime>

using namespace std;

int main() {
  srand(time(NULL));
  int birthdays[10000][50];
  int numMatches;
  int trials=10000,check;
  for(int n=0;n<trials;n++)
    {
    for(int j=0;j<50;j++)
      {
        birthdays[n][j]=rand()%365+1;
      }
    }
  for(int i=2;i<=50;i++)
     {
       numMatches=0;
       for(int n=0;n<trials;n++)
          {
         check=1;
         for(int j=0;j<i;j++)
            {
              for(int k=j+1;k<=i;k++)
                {
                  if(birthdays[n][j]==birthdays[n][k]&&check)
                    {
                     numMatches++;
                     check=0;
                    }
                }
            }
      }
 cout << "Probability of " << i << " people in a room sharing a birthday is \t" <<
     (static_cast<float>(numMatches) / (trials)) << endl;
   }
}

答案 2 :(得分:0)

考虑一下这里发生了什么:

    for(int j = 1; j <= trials; j++) {
        for(k = 1; k <= i; k++)
            birthdays[k] = (rand() % 365) + 1;
        for(m = 1; m <= i; m++)
            birthdays[m] = (rand() % 365) + 1;
        if(birthdays[k] == birthdays[m])
            ++numMatches;
    }

您通过i生日并分配一个随机数,然后您通过相同的i生日并为其分配一个新的随机数。然后,您尝试仅找到一个km值的匹配项(两者都碰巧等于i+1,这不是设置的值之一!)。

我的建议是将问题分解成更小的单元,这样可以更容易地弄清楚如何编写代码 - 这是我试图编写的函数。

/* randomizeBirthdays()
 *   Put n random birthdays into the pre-allocated array birthdays.
 *   birthdays must of course be of length <= n.
 */
void randomizeBirthdays(int * birthdays, int n);

/* hasMatchingBirthdays()
 *   Check if birthdays array has two people with the same birthday
 *   in the first n entries.
 *   Return value is boolean.
 */
bool hasMatchingBirthdays(int * const birthdays, int n);

/* probabilityOfMatch()
 *   Calculate the probability that at least 2 out of n people will
 *   have the same birthday, using nTrials number of trials.
 *   Return value is double.
 */
double probabilityOfMatch(int n, int nTrials);

如果你这样分解它会变得更容易编写并且更容易排除故障。

答案 3 :(得分:0)

正如我在评论中所说:

  

我认为你的目的是测试2-50人的2人共用   生日,如果2-50人分享生日,就像你在输出中说的那样。和   23人中有2人有50.7%,而不是24人。

我完全重写了你的代码:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

#define DAYS_IN_YEAR 365
#define TRIALS 10000

void clearArray (bool * array)
{
    for (int i = 0; i < DAYS_IN_YEAR; i++)
        array[i] = false;
}

int main()
{
    srand(time(NULL));
    bool birthdays[DAYS_IN_YEAR]; //we are trying to hit same day in year twice
    int r, numMatches;

    for(int i = 2; i < 50; i++)
    {
        numMatches = 0;

        for(int j = 0; j < TRIALS; j++)
        {
            clearArray(birthdays);

            for(int k = 0; k < i; k++)
            {
                r = rand() % DAYS_IN_YEAR; // == 0-364
                if (birthdays[r])
                {
                    numMatches++;
                    break;  // 2 people already have same birthdays here
                }
                birthdays[r] = true;
            }
        }

        cout << "Probability of 2 people having same birthday in room of " << i << " people is "
             << (float)numMatches / TRIALS << endl;

    }
 }

输出:

  

在23个人的房间里有2个人生日相同的概率是0.516