我正在为我的Computing I类编写一个小程序,其中程序接收用户决定的多个整数并计算点积。我能够使用迭代方法成功地完成它,但现在我们还必须使用递归来完成它。我计算点积的函数返回了大量不正确的数字。有时它会返回数组中最后两个值的乘积的两倍的值,当有4个其他集合没有被添加时。其他时候,我将有2个3个小数组的数组,并且返回的值是80万。这是递归函数:
//A and B are the arrays that will be dotted together, and n is number of
//elements in each array
int dotP( int *A, int *B, int n ) {
if( n==1 ) return A[0] * B[0] ;
return A[n-1] * B[n-1] + dotP( &A[n-1], &B[n-1], n-1);
}
答案 0 :(得分:3)
究竟发生了什么
A[n-1]*B[n-1] + A[n-1 + n-2]*B[n-1 + n-2]+....
这是因为第二次递归调用,你传递的是n-1
元素的地址。当它在第二次调用中计算A[n-2]
时,它从n-2
元素开始有效地指向n-1
nd元素,该元素是来自数组的第一个元素的2*n-3
。
n
之后的数组中的值是垃圾(假设您已分配n
个元素,或者您可能已分配超过n
但未初始化它们。因此,你得到了随机的答案。
您不需要将当前数组元素的地址传递给每个递归调用。您只需传递第一个元素的地址,即A
或&A[0]
。那你的代码工作正常。这是怎么做的:
int dotP( int *A, int *B, int n ) {
if( n==1 ) return A[0] * B[0] ;
return A[n-1] * B[n-1] + dotP( A, B, n-1) ;
}
由于A
和B
已经是指针,因此您只需直接传递它们。希望这会有所帮助。
答案 1 :(得分:2)
不
... + dotP( &A[n-1], &B[n-1], n-1 );
但
... + dotP( &A[0], &B[0], n-1 );
因为看起来你想要处理数组的最后一项,然后将第一个(n-1)个元素传递给递归调用。记住数组总是被作为指向它们的第一个元素的指针来处理,除非你做的比这更棘手。
问题已经解决了,但是出于教育目的,尝试这个替代方案:你可以处理第一个元素并传递剩下的“尾巴”,这对LISP粉丝来说可能更令人满意:
return A[0] * B[0] + dotP( &A[1], &B[1], n-1 );
除此之外,您可以传递A + 1而不是& A [1]。
答案 2 :(得分:0)
为什么不能更好地使用:
int dotP( int *A, int *B, int n )
{
if (n) return A[0] * B[0] + dotP(A + 1, B + 1, n-1);
else return 0;
}
或以更紧凑的形式:
int dotP(int *A, int *B, int n)
{
if (n) return A[0] * B[0] + dotP(++A, ++B, --n);
else return 0;
}