Сделать из цикла рекурсию

введите сюда описание изображения

Есть код на плюсах, который циклично высчитывает текущий член ряда:

    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 шт):

Автор решения: Harry

Вот ваш ряд итеративно и рекурсивно - 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;
}
→ Ссылка
Автор решения: Павел Ериков

Вообще у вас ошибки еще на методе с циклом:

  1. Формула конечно не очень понятна на картинке, но вряд ли рекуррентное соотношение будет содержать в себе тот член, который и нужно рассчитать. Я про 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 в вашем случае. Легко запутаться конечно :)

  2. Изначально переменная current я думаю должна равняться pow(x, 3), но вы не написали чему равен первый член, так что углубляясь мы дойдем до i = -1, где попытаемся делить на 0. Так что предположу, что C0 = x ^ 3.

  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, то все, ошибка!

→ Ссылка