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

时间:2013-11-23 16:14:19

标签: c++ combinations probability factorial

该程序询问用户掷硬币的次数(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);

这是我的事实函数的伪代码:

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

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

2 个答案:

答案 0 :(得分:1)

您尚未提及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)

答案 1 :(得分:1)

你超过了长期的最大值。因子增长如此之快,以至于你需要正确的数字类型 - 这取决于你需要什么样的价值。

Long是有符号整数,一旦传递2 ^ 31,该值将变为负数(它使用2的补码数学)。

使用unsigned long会给你一点时间(一点多),但对于阶乘,它可能不值得。如果您的编译器支持long long,那么请尝试“unsigned long long”。那将(通常,取决于编译器和CPU)加倍你正在使用的位数。

您也可以尝试切换为使用double。你将面临的问题是随着数字的增加你会失去准确性。 double是浮点数,因此您将拥有固定数量的有效数字。如果您的最终结果是近似值,这可能会正常工作,但如果您需要精确值,则无效。

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