【问题标题】:Calculating Probability C++ Bernoulli Trials计算概率 C++ 伯努利试验
【发布时间】:2013-11-24 00:29:13
【问题描述】:

程序询问用户掷硬币的次数(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,就会发生这种情况。对于应该是 xxx 的值,我得到了 0 和负值。

调试,我注意到 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;
}

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

【问题讨论】:

  • 您可能会遇到整数溢出。尝试将事实函数的类型更改为 double,看看是否接受了更高的值。
  • 这里:stackoverflow.com/a/4701106/576911 是如何计算 nCk 时溢出的风险最小,如果确实发生了溢出,它不会默默地这样做。

标签: c++ combinations probability factorial


【解决方案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)

【讨论】:

    【解决方案2】:

    您超出了 long 的最大值。阶乘增长如此之快,以至于您需要正确的数字类型——具体的类型取决于您需要的值。

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      • 2019-09-05
      • 1970-01-01
      • 2015-06-17
      • 1970-01-01
      • 2023-02-01
      • 2017-06-27
      相关资源
      最近更新 更多