2013-09-24 5 views
1

Я пишу небольшую программу для моего класса 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

Вы можете разместить код, который выделяет массивы A и B, и вызывает функцию? Возможно, они неправильно назначены или неправильно инициализированы. – Owen

+0

Можете ли вы предоставить ввод данных образца? –

+0

Думали ли вы попробовать напечатать номера, которые вы обрабатываете в функции?'printf (" A [0] =% d, B [0] =% d \ n ", A [0], B [0]);' в коде 'if' и' int dp = dotP (& A [n-1], & B [n-1], n-1); printf («A [% d] =% d, B [% d] =% d, DotProduct =% d \ n", n-1, A [n-1], n-1, B [n-1] , dp); return A [n-1] * B [n-1] + dp; 'для 'else' части кода. Это покажет вам, что все идет по-настоящему. Возможно, вы даже напечатали массивы от элемента 0 до «n-1» для хорошей оценки. Это самый простой способ отладки, если у вас нет отладчика (а иногда даже если у вас есть отладчик). –

ответ

3

Что именно происходит,

A[n-1]*B[n-1] + A[n-1 + n-2]*B[n-1 + n-2]+.... 

Это происходит потому, что для 2-го рекурсивного вызова, вы передаете адрес n-1-го элемента. Когда он вычисляет A[n-2] во втором вызове, он эффективно указывает на n-2-й элемент, начиная с n-1-го элемента, который равен 2*n-3 rd из первого элемента массива.

Значения в массиве после 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 указатели уже, вы просто передать их directly.Hope это помогает.

+0

Ваше решение решило это; Благодаря! –

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].

+1

Спасибо за показ хвостовой рекурсивной формы. Это радует не только программистов LISP. Это более естественная форма. – paddy

+1

@paddy Последний пример не является хвостом рекурсивным. Для этого вам нужен аккумулятор, чтобы вы избавились от продолжения +. – Sylwester

+1

@DarenW и @paddy У меня также есть те же сомнения, что и @Sylwester. Как он будет поддерживать оптимизацию хвостовой рекурсии? Текущий стек по-прежнему должен поддерживаться, так как нам нужно добавить результат с помощью 'A [0] * B [0]' – thefourtheye

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; 
} 
Смежные вопросы