2

どうやら私は実際には、多くの試行 (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

4 に答える 4

2

問題は C++ コードではありません。あなたは数学にタイプミスがあるだけです。そのはず:

power = (num * (num - 1.0) / 2.0);
chance = 1.0 - pow(constant, power);
于 2013-09-16T02:58:44.697 に答える
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% を超える」というおなじみの結果につながります。

于 2013-09-16T02:56:25.580 に答える
1

364/365 ≈ 0.0027 を大きな数の累乗で計算しているため、ゼロよりわずかに大きい数値になります。要求された出力精度に丸められると、結果はゼロになります。

于 2013-09-16T02:57:43.770 に答える
0

本質的にあなたは新しい質問を作成したので、私は新しい答えを作成します。現在、誕生日をループしている間、誕生日を変更し続けています。これが物事がうまくいかない理由です。誕生日が同じかどうかをテストするには、ネストされたループが 2 つ必要です (または、賢く並べ替えることができれば、隣接するものだけをチェックします。おそらく 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;
}

注 - これをコンパイル/テストする機会がありませんでした。それは「本質的に」正しいはずです。問題が発生した場合はお知らせください。

于 2013-09-18T20:37:53.180 に答える