声明/计算的生日悖论

时间:2013-09-16 02:44:59

标签: c++

显然我实际上是想创建一个随机分配许多试验生日的数组(5000)。然后假设每次为2至50人至少有2个生日,并将结果除以5,000以获得近似概率。我相信我的循环搞砸了,想要一些反馈。不是代码,我想知道到底出了什么问题,以及我是如何搞砸它的。

int main()
{
    const int trials(5000);
    double total;
    int count(0), birthdays[49];

    srand(time(NULL));

    for (int i = 2; i <= 50; i++)
    {
        for (int k = 0; k < trials; k++)
        {
            fillUp(birthdays, 49);
            for (int j = i + 1; j <= 50; j++)
            {
                if (birthdays[i] == birthdays[j])
                {
                    count += 1;
                }
            }
        }
        total = count / 5000.0;
        cout << "For " << i << " the probability is " << total << endl;
    }
    return 0;
}

void fillUp(int birthdays [], int size)
{
    for (int i = 0; i < size; i++)
    {
        birthdays[i] = rand() % 365 + 1;
    }
}

输出:

For 2 the probability is 0.1286
For 3 the probability is 0.2604
...
...
For 49 the probability is 3.9424
For 50 the probability is 3.9424

任何帮助都会非常感激。

4 个答案:

答案 0 :(得分:2)

问题不在于C ++代码;你的数学中只有一个错字。它应该是:

power = (num * (num - 1.0) / 2.0);
chance = 1.0 - pow(constant, power);

答案 1 :(得分:1)

您可能知道公式,但您的代码未正确实现。以下是一些正确实现公式的C代码:

#include <stdio.h>

int main(void) {
  double p;
  int ii;
  int people;
  for (people = 3; people < 50; people++) {
    p = 1;
    for (ii = 1; ii < people; ii++) {
      p *= (365.0 - ii) / 365.0;
    }
    printf("for %d people, probability is %.4f\n", people, 1 - p);
  }
  return 0;
}

这导致以下输出:

for 1 people, probability is 0.0000
for 2 people, probability is 0.0027
for 3 people, probability is 0.0082
for 4 people, probability is 0.0164
for 5 people, probability is 0.0271
for 6 people, probability is 0.0405
for 7 people, probability is 0.0562
for 8 people, probability is 0.0743
for 9 people, probability is 0.0946
for 10 people, probability is 0.1169
for 11 people, probability is 0.1411
for 12 people, probability is 0.1670
for 13 people, probability is 0.1944
for 14 people, probability is 0.2231
for 15 people, probability is 0.2529
for 16 people, probability is 0.2836
for 17 people, probability is 0.3150
for 18 people, probability is 0.3469
for 19 people, probability is 0.3791
for 20 people, probability is 0.4114
for 21 people, probability is 0.4437
for 22 people, probability is 0.4757
for 23 people, probability is 0.5073
for 24 people, probability is 0.5383
for 25 people, probability is 0.5687
for 26 people, probability is 0.5982
for 27 people, probability is 0.6269
for 28 people, probability is 0.6545
for 29 people, probability is 0.6810

导致熟悉的结果“只有23个人的机会是> 50%”。

答案 2 :(得分:1)

你计算364/365≈0.0027到某个大数的幂,这导致数字只略高于零。舍入到请求的输出精度时,结果为零。

答案 3 :(得分:0)

从本质上讲,您已经创建了一个新问题,因此我将创建一个新答案。现在你在循环时不断改变生日;这就是事情不起作用的原因。你需要两个嵌套循环来测试相同的生日(或者如果你很聪明,你可以对它们进行排序,然后只检查相邻的那些。当n = 50时它可能更快。)

您还需要在第一个生日开始测试(您的数组是基数0 - 但是您从i = 2开始)。对于每个试验,您可以在匹配之前查看需要比较的人数。正确的代码看起来像这样(请注意,我为房间里的每个人运行5000次试验;当你有3,4,5个人时,你可以通过检查匹配来提高效率......基于相同的人样本,但在抽样中会有一些相关性。)

已编辑 - 测试此代码,似乎编译并运行正常。结果看起来接近预期值。

#include <iostream>

void fillUp(int birthdays [], int size)
{
    for (int i = 0; i < size; i++)
    {
        birthdays[i] = rand() % 365 + 1;
    }
}

int main(void) {
int birthdays[50];
int trials = 5000;
int flag;
double total;
int collisions[50];
   // number of people "in the room"
   for (int i = 2; i < 50; i++)
      {
      collisions[i] = 0;
      // do 5000 trials:
      for (int t = 0; t < trials; t++)
       {
        fillUp(birthdays, i);
        flag = 0;
        // compare all pairs (j,k):
        for (int j = 0; j < i - 1 && flag == 0; j++)
        {
          for (int k = j + 1; k < i && flag == 0; k++ )
          {
            if (birthdays[k] == birthdays[j])
            {
              collisions[i]++;
              flag = 1;
            }
          }
        }
      }
    total = collisions[i] / 5000.0;
    std::cout << "For " << i << " people in the room the probability is " << total << std::endl;
    }
return 0;
}

注意 - 我没有机会编译/测试这个;它本质上应该是“正确的”。如果它出现问题,请告诉我。