有人可以告诉我为什么我的组合函数总是得出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;
}
答案 0 :(得分:9)
您的直接问题是您将可修改的引用传递给函数。这意味着您在此处具有未定义的行为:
return (n+1) * factorial(n);
// ^^^ ^^^
因为factorial(n)
修改了n
,并且不确定地以(n+1)
排序。 Combination()
中存在类似的问题,其中b
在同一表达式中被修改了两次:
return permutation(a,b) / factorial(b);
// ^^^ ^^^
如果按值传递n
,a
和b
,您将获得正确的结果,如下所示:
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 long
或unsigned 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)
您不使用指针值进行计算,而使用指针地址进行计算。