C ++组合函数总是产生0

时间:2018-10-04 10:55:07

标签: c++ recursion factorial

有人可以告诉我为什么我的组合函数总是得出0吗? 我还尝试使其不使用置换函数来计算组合,但是阶乘仍然是0;

#include <iostream>
#include <cmath>

using namespace std;

int factorial(int& n)
{
  if (n <= 1)
  {
     return 1;
  }
  else 
  {
    n = n-1;
    return (n+1) * factorial(n);
  }
}
int permutation(int& a, int& b)
{
  int x = a-b;
  return factorial(a) / factorial(x);
}
int Combination(int& a, int& b)
{
   return permutation(a,b) / factorial(b);
}

int main()
{
   int f, s;
   cin >> f >> s;

   cout << permutation(f,s) << endl;
   cout << Combination(f,s);


  return 0;
 }

2 个答案:

答案 0 :(得分:9)

您的直接问题是您将可修改的引用传递给函数。这意味着您在此处具有未定义的行为:

return (n+1) * factorial(n);
//      ^^^             ^^^

因为factorial(n)修改了n,并且不确定地以(n+1)排序。 Combination()中存在类似的问题,其中b在同一表达式中被修改了两次:

return permutation(a,b) / factorial(b);
//                  ^^^            ^^^

如果按值传递nab ,您将获得正确的结果,如下所示:

int factorial(int n)

现在,factorial()得到了自己的n的副本,并且不会影响您要与之相乘的n+1


虽然我们在这里,但我应该指出代码中的其他一些缺陷。

  • 避免使用using namespace std;-它有陷阱给那些粗心的人(甚至是谨慎的人!)。

  • 按值(而不是按引用)传递值后,您可以编写factorial()而无需修改n

    int factorial(const int n)
    {
        if (n <= 1) {
            return 1;
        } else {
            return n * factorial(n-1);
        }
    }
    
  • 考虑使用迭代代码来计算阶乘。

  • 我们可能应该使用unsigned int,因为该操作对于负数没有意义。您可以考虑使用unsigned longunsigned long long获得更大的射程。

  • 计算一个阶乘并除以另一个因数不仅效率低下,而且还存在不必要的溢出风险(当a低至13,具有32位int时)。取而代之的是,我们可以乘以另一个数字:

    unsigned int permutation(const unsigned int a, const unsigned int b)
    {
        if (a < b) return 0;
    
        unsigned int permutations = 1;
        for (unsigned int i = a;  i > a-b;  --i) {
            permutations *= i;
        }
    
        return permutations;
    }
    

    a较小时,此方法适用于更高的b

  • 我们不需要<cmath>标头。


建议的固定代码:

unsigned int factorial(const unsigned int n)
{
    unsigned int result = 1;

    for (unsigned int i = 2;  i <= n;  ++i) {
        result *= i;
    }

    return result;
}

unsigned int permutation(const unsigned int a, const unsigned int b)
{
    if (a < b) return 0;

    unsigned int result = 1;
    for (unsigned int i = a;  i > a-b;  --i) {
        result *= i;
    }

    return result;
}

unsigned int combination(const unsigned int a, const unsigned int b)
{
    // C(a, b) == C(a, a - b), but it's faster to compute with small b
    if (b > a - b) {
        return combination(a, a - b);
    }

    return permutation(a,b) / factorial(b);
}

答案 1 :(得分:-7)

您不使用指针值进行计算,而使用指针地址进行计算。