计算概率C++伯努利试验

Calculating Probability C++ Bernoulli Trials

本文关键字:概率 C++ 计算      更新时间:2023-10-16

程序要求用户翻转硬币的次数(n;试验次数)。

成功被认为是一个头脑。

该程序完美地创建了一个介于0和1之间的随机数。0被认为是成功的象征。

然后,该程序应该输出获得x个磁头数量的期望值。例如,如果硬币被翻转了4次,使用公式,以下概率是多少

nCk * p^k * (1-p)^(n-k)
Expected 0 heads with n flips: xxx
Expected 1 heads with n flips: xxx
...
Expected n heads with n flips: xxx

当用"更大"的数字做这件事时,这些数字会变成奇怪的值。如果在输入中输入15或20,就会发生这种情况。我已经得到了0和负值的值,应该是xxx。

在调试过程中,我注意到nCk是负数,对上限值不正确,认为这就是问题所在。我使用这个公式进行组合:

double combo = fact(n)/fact(r)/fact(n-r);

这是我的fact函数的伪代码:

long fact(int x)
{
     int e; // local counter
     factor = 1;
     for (e = x; e != 0; e--)
     {
         factor = factor * e;
     }
     return factor;
}

有什么想法吗?我的猜测是我的阶乘或组合函数超过了最大值或其他什么。

您还没有提到factor是如何声明的。我认为你得到了整数溢出。我建议你用替身。这是因为既然你在计算期望值和概率,你就不应该太关心精度。

尝试将事实函数更改为.

double fact(double x)
{
     int e; // local counter
     double factor = 1;
     for (e = x; e != 0; e--)
     {
         factor = factor * e;
     }
     return factor;
}

编辑:同样要计算nCk,不需要计算3次阶乘。您可以通过以下方式简单地计算此值。

if k > n/2, k = n-k.
       n(n-1)(n-2)...(n-k+1)
nCk = -----------------------
          factorial(k)

您超过了long的最大值。因式增长如此之快,以至于你需要正确的数字类型——这是什么类型取决于你需要什么值。

Long是一个有符号整数,一旦您通过2^31,该值就会变为负数(使用2的补码数学)。

使用无符号long会为您争取一点时间(多一位),但对于阶乘来说,这可能不值得。如果您的编译器支持long-long,请尝试"无符号long-long"。这将(通常取决于编译器和CPU)使您使用的位数增加一倍。

您也可以尝试切换为使用double。你将面临的问题是,随着数字的增加,你将失去准确性。双精度是一个浮点数,因此您将拥有固定数量的有效数字。如果你的最终结果是近似值,这可能还可以,但如果你需要确切的值,那就行不通了。

如果这些解决方案都不适合你,你可能需要使用一个"无限精度"的数学包,你应该能够搜索它。你没有说你使用的是C还是C++;使用C++会更令人愉快,因为它将提供一个类似数字的类,并使用标准算术运算符。