Алгоритм для суммы ряда с точностью ε=0.0001 и проверкой по формуле

Написала код по заданию, сумма не выводится

задание

оригинал кода

#include <iostream>
#include <locale>
#include <cmath>

using namespace std;

int fact(int a) // возвращает целочисленное значение и принимает целочисленное число
{
    if (a == 0) // условия выхода из рекурсии
        return 0;
    if (a == 1)
        return 1;
    return a * fact(a - 1);
}

int main()
{
    setlocale(LC_ALL, "RUS");
    float x;

    for (x = -1; fabs(x) < 1; x += 0.01f)
    {
        double s = 0, slag = 0, eps = 0.0001f;
        int n = 0, znak = 1;

        while (slag > eps)
        {
            slag = (znak * fact(2 * n) / pow(4, n) * pow(fact(n), 2) * (2 * n + 1))
                   * pow(x, 2 * n + 1);
            s += slag;
            n += 1;
            znak = -znak;
        }
        cout << "Сумма ряда равна=" << s << " при значении x=" << x << endl;
    }
}

Ответы (1 шт):

Автор решения: Old Skull

Вычислять каждый раз факториал -- не очень хорошо. Да ещё дважды -- для числителя и знаменятеля. Тем более, когда итераций может быть много. Полагаю, именно для этого и предписано использовать рекуррентные соотношения при вычислении очередного члена ряда.

Вот как это может выглядеть на примере C++ 23. На эффективность/идиоматичность/т.п. не претендую. Проверял в онлайн-сервисе OnlineGDB

#include <iostream>
#include <functional>
#include <cmath>

double arsh(const double x, const double epsilon)
{
    const double expected = asinh(x);
    
    std::function<double(double prev, const int n, const int sign, double result)> sum;

    sum = [x, expected, epsilon, &sum](double prev, const int n, const int sign, double result) -> double
    {
        if ( fabs(result - expected) > epsilon )
        {
            prev *= x * x * (2*n - 1) / (2*n + 1) * (2*n - 1) / 2 / n;
            result += sign * prev;
            return sum(prev, n + 1, -sign, result);
        }
        
        return result;
    };
    
    return sum(x, 1, -1, x);
}

int main()
{
    double x = 0.75;
    double epsilon = 0.00000008;
    double actual = arsh(x, epsilon);
    double expected = asinh(x);
    printf ("epsilon = %.15f\n", epsilon);
    printf ("asinh(%.5f) = %.15f\n", x, expected);
    printf ("arsh(%.5f)  = %.15f\n", x, actual);
    printf ("|expected - actual| = %.15f\n", fabs(expected - actual));
    return 0;
}
epsilon = 0.000000080000000
asinh(0.75000) = 0.693147180559945
arsh(0.75000)  = 0.693147124543558
|expected - actual| = 0.000000056016387

P.S. Разумеется, можно и без рекурсивной лямбды обойтись, просто мне было интересно, т.к. в С++ я 0.

→ Ссылка