在一次采访中,我得到了以下问题,最初使用笔/纸解决,然后通过程序验证结果。
问题如下:
有 A、B 和 C 三个人。每个人能够分别以 6/7、4/5 和 3/4 的概率击中目标。如果他们每个人都开一枪,那么他们中恰好有两个人会击中目标的概率是多少?
答案是:
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。
- 标准::mt19937_64
- std::ranlux48_base
- std::minstd_rand0
更新2: 考虑到这个问题,我已经走上了下面的路。比率 27/70 由 27 和 70 组成,它们都是互质的,并且 4x10^9 下的 70 因子大约是 57x10^6 或所有数字的 1.4%。因此,从 [0,4x10^9] 之间随机选择的两个数字中获得 27/70 的“精确”比率的概率大约为 1.4%(因为在 4x10^9 内有更多的 27 因子) - 所以得到确切的比率非常低,无论试验次数如何,这个数字都是恒定的。
现在,如果有人谈论厚边界 - 即:在 70 +/5 的因子范围内的数字,这会增加在 [0,4x10^9] 范围内随机选择一对数字的概率,这将给出在指定/相关公差范围内的比率大约为 14%,但使用这种技术,我们可以获得的最佳结果与精确值相比平均精确到大约 5 个小数位。这种推理方式正确吗?