任务是计算输入的自然数的表达式。
我也知道(-1)^ p确定此数组是递减还是递增,但不知道如何在我的代码中使用p 我不太清楚如何将它们放在一起,这是我到目前为止所提出的并且它没有什么特别之处,因为我仍然无法理解如何在程序中编写它。
public static int calculateExpression(int n, int k,int p) {
if(k<0 || n<k)
{
return 0;
}
// Find factorial of n
int n_fac = 1;
for (int j = 1; j <= n; j++) {
n_fac = n_fac * j;
}
// Find factorial of k
int k_fac = 1;
for(int i = 1; i<=k; i++) {
k_fac = k_fac * i;
}
// Find n-k fac
int n_k = n-k;
int n_k_fac = 1;
for(int l = 1; l<=n_k;l++) {
n_k_fac*=l;
}
// n/k = n!/k!(n-k)!
double resultOf_n_kDivision = n_fac/k_fac*n_k_fa;
System.out.println(resultOf_n_kDivision);
return n_k_fac;
}
答案 0 :(得分:1)
阶乘函数是一个非常快速增长的函数,因此分别计算分子和分母可能不是一个好主意,因为即使相对较小的n
值也可能导致溢出。
让我们看一下用于计算系数的迭代方法:
如果我们知道当前的那个,我们就可以计算出该行的下一个系数。因此,我们可以逐步计算S
中的每个术语,同时不太关心溢出问题。
static int calculateExpression(int n, int k, int p)
{
// first term of the row is (n, 0) = 1
int binom = 1;
// Iteratively find (n, k)
for (int i = 0; i < k; i++)
binom = (binom * (n - i)) / (i + 1);
// sum the series
int S = binom;
for (int i = 0; i < p; i++) {
// "trick": multiply with a minus sign each time to flip the sign
binom = (-binom * (n - k - i)) / (k + i + 1);
S += binom;
}
return S;
}
更新:并行数值测试:
n k p | orig new
----------------------
5 3 2 | 6 6
10 4 1 | -42 -42
12 3 7 | 44 44
15 8 6 | 3433 8 // integer overflow occurred with the original method
正如您所看到的那样,两个函数在n = 15
的最后一行之前是一致的,因为15! = 1307674368000
比大多数Java实现中的int
的最大正值大得多(32位)。
答案 1 :(得分:0)
使用抽象来更好地解决问题;定义fac
和over
。
然后问题变成:
public static int calculateExpression(int n, int k,int p) {
int sum = 0;
int minus1toP = 1;
for (int i = 0; i <= p; i++) {
sum += minus1toP * over(n, ...);
minus1toP = -minus1toP;
}
return sum;
}
static int over(int n, int k) {
return fac(n) / fac(k) / fac(n - k);
}
static int fac(int n) {
int f = 1;
for(int i = 2; i <= n; i++) {
f *= i;
}
return f;
}
我没有提供整个解决方案(...),但可能已经太多了。
答案 2 :(得分:0)
我没有真正得到你的问题,但你可以使用它。
public static double combination(int n, int k)
{
double nFactorial = getFactorialFromNToK(n, k);
double kFactorial = getFactorialFromNToK(k, 1);
return nFactorial / kFactorial;
}
public static double getFactorialFromNToK(double n, double k)
{
double factorial = 1;
for (; n - k + 1 > 0; n--)
{
factorial *= n;
}
return factorial;
}
这是对二项式扩展中项的系数的nCk的评估。
如果nCn是扩展中的一个术语,那么它会收敛,如果它在扩展中不作为术语存在,那么它就不会收敛。因此,如果它是一个自然数字扩展,那么它将始终收敛。
答案 3 :(得分:0)
更好的解决方案是使用lngamma函数而不是阶乘。这是计算因子的更有效方法。自然日志意味着划分大数字不会有问题。