インタビューで、私は次の問題を与えられました。最初はペン/紙を使用して解決し、次にプログラムを介して結果を検証しました。
質問は次のとおりです。
A、B、C の 3 人がいます。各人は、それぞれ 6/7、4/5、3/4 の確率で的を射ることができます。それぞれが 1 発ずつ発射した場合、そのうちの 2 発が標的に命中する確率は?
答えは次のとおりです。
P(...) = P(A)*P(B)*(1-P(C)) +
P(B)*P(C)*(1-P(A)) +
P(C)*P(A)*(1-P(B))
= 27.0/70.0
= 38.57142857142857142857142857142857142857....%
以下は、問題に対する私の解決策です。
#include <cstdio>
#include <cctype>
#include <ctime>
#include <random>
int main()
{
std::mt19937 engine(time(0));
engine.discard(10000000);
std::uniform_real_distribution<double> uniform_real(0.0,1.0);
double prA = (6.0 / 7.0);
double prB = (4.0 / 5.0);
double prC = (3.0 / 4.0);
std::size_t trails = 4000000000;
std::size_t total_success = 0;
for (std::size_t i = 0; i < trails; ++i)
{
int current_success = 0;
if (uniform_real(engine) < prA) ++current_success;
if (uniform_real(engine) < prB) ++current_success;
if (uniform_real(engine) < prC) ++current_success;
if (current_success == 2)
++total_success;
double prob = (total_success * 1.0) / (i+1);
if ((i % 1000000) == 0)
{
printf("%05d Pr(...) = %12.10f error:%15.13f\n",
i,
prob,
std::abs((27.0/70.0) - prob));
}
}
return 0;
}
問題は次のとおりです。実行する試行の数に関係なく、確率は約 0.3857002101 で平坦になります。コードに何か問題がありますか?
インタビュアーは、シードに関係なく、100 万回の試行で結果を小数点以下 9 桁の精度に収束させるのは簡単なことだと述べました。
私のコードのどこにバグがあるかについてのアイデアはありますか?
更新 1: 次のジェネレーターを使用して上記のコードを試してみましたが、ほぼ同時に 10 ^ 9 を試してみました。
- std::mt19937_64
- std::ranlux48_base
- std::minstd_rand0
更新 2: 問題について考えて、私は次の道をたどりました。27 と 70 で構成される比率 27/70 は互いに素であり、4x10^9 未満の 70 の因数はおよそ 57x10^6 またはすべての数の約 1.4% です。したがって、[0,4x10^9] の間でランダムに選択された 2 つの数値から 27/70 の「正確な」比率を取得する確率は、およそ 1.4% です (4x10^9 内には 27 の因数がさらにあるため)。正確な比率は非常に低く、その数は試行回数に関係なく一定です。
ここで、厚い境界について話す場合-つまり、70 + / 5の係数の範囲の数値の場合、[0,4x10 ^ 9]の範囲内で数値のペアをランダムに選択する確率が高くなります。指定された/関連する許容範囲内の比率は約 14% ですが、この手法を使用すると、正確な値と比較した場合、平均で約 5 桁の精度が得られます。この推論の仕方は正しいでしょうか?