Сделать из цикла рекурсию
Есть код на плюсах, который циклично высчитывает текущий член ряда:
double current = pow(x, 3) / 2;
double last;
int j = 0;
while (j < i) {
last = current;
current = last - 1 * pow(x, 3) / ((long double)i + 1);
j++;
}
return current;
}
Проблема в том, что мой код через рекурсию дает другие результаты:
double currentNum(double base, int number) {
if (number == 0) {
return pow(base, 3);
}
else if (number == 1) {
return pow(base, 3) / 2;
}
else {
return currentNum(base, number - 1) * pow(base, 3) / ((long double)number + 1);
}
}
В чем может быть ошибка?
Ответы (2 шт):
Вот ваш ряд итеративно и рекурсивно - https://ideone.com/mX6eUi
double iterate(double x, double eps)
{
x = x*x*x;
double term = x/2, sum = x/2;
for(int k = 3; abs(term) > eps; ++k)
sum += (term *= x/k);
return sum;
}
double recursion(double x, double eps, double term = 1, int k = 2)
{
if (abs(term) < eps) return 0;
term *= x*x*x/k;
return term + recursion(x,eps,term,k+1);
}
int main()
{
for(double x = 0; x < 2; x+= 0.2)
cout << setw(10) << x
<< setw(15) << iterate(x,1e-8)
<< setw(15) << recursion(x,1e-8) << endl;
}
Вообще у вас ошибки еще на методе с циклом:
Формула конечно не очень понятна на картинке, но вряд ли рекуррентное соотношение будет содержать в себе тот член, который и нужно рассчитать. Я про
Ci = (Ci) - (1 * x ^ 3 / (i + 1)), я больше чем на 100% процентов уверен, что формула должна быть такой:Ci = (C[i - 1]) * x ^ 3 / (i + 1), то есть предыдущий член * наx ^ 3и разделить наi + 1.То есть для расчета
currentнужно поменять формулу с:current = last - 1 * pow(x, 3) / ((double)i + 1);на:
current = last * pow(x, 3) / ((double)j + 1);Хочу заметить, что вы делите всегда на
i + 1хотяiу вас постоянна, а вотjкак раз и изменяется, так что нужно делить наj + 1в вашем случае. Легко запутаться конечно :)Изначально переменная
currentя думаю должна равнятьсяpow(x, 3), но вы не написали чему равен первый член, так что углубляясь мы дойдем доi = -1, где попытаемся делить на0. Так что предположу, чтоC0 = x ^ 3.И так после 2 пункта у вас в цикле
last = current, то естьlast = C0, а потом по идее должно высчитыватьсяC1, ноj = 0следовательно вы еще раз высчитываетеC0. Нужноj++добавить перед нахождением следующего члена.
В итоге вот пример кода через цикл:
double x = 1;
double current = pow(x, 3);
double last;
int j = 0;
int i = 3;
while (j < i) {
last = current;
j++;
current = last * pow(x, 3) / ((double)j + 1);
}
cout << current << endl;
Предположив, что C0 = x ^ 3, при x = 1, i = 3 имеем:
1 * (1 / 2) * (1 / 3) * (1 / 4) = 0.4(16)
Такой же результат мы должны получить и при рекурсивном подходе.
Сразу хочу сказать, что лучше вместо pow(x, 3) использовать x*x*x, а еще лучше рассчитать сразу x ^ 3 и потом уже умножать, но на результат программы это не влияет. А преподаватель кому вы будете сдавать эту задачу вряд ли придерется к эффективности :)
Рекурсивный подход:
Вообще логика у вас правильна, при подходе с циклом мы идем от C0 до Ci, а при рекурсии, конечно же проще начинать с конца.
И в вашей функции я сразу вижу такую строчку if(number == 0) return pow(base, 3); то есть пункт 2 (который выше) имеет место быть.
И на удивление у вас одна лишь ошибка, когда number == 1 у вас возвращается pow(base, 3) / 2, но это не так. C1 = C0 * x ^ 3 / 2 => C1 = x ^ 3 * x ^ 3 / 2 => C1 = x ^ 6 / 2.
Да вы можете изменить степень 3 на 6, но зачем эта проверка вообще? :) Можете спокойно от нее избавиться.
Вот пример рекурсивного подхода (названия переменных поменял для понимания):
double currentNum(double x, int i) {
if (i == 0) return pow(x, 3);
return currentNum(x, i - 1) * pow(x, 3) / ((double)i + 1);
}
Результат программы такой же:
(1 / 4) * (1 / 3) * (1 / 2) * 1
Но тут хочу сказать, что выбор x = 1 плохой т.к. ваш вариант рекурсивной функции при x = 1 будет выдавать правильный ответ, но если x поменять например на 2, то все, ошибка!
