Моя программа на C++ не может рассчитать эту серию для числа Эйлера

Вот программа на C++, которую я написал для решения вышеупомянутой серии:

#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;

int factorial(int a)
{
    if (a > 1)
        return a * factorial(a - 1);
    else
        return 1;
}

float series(float x, int n, float b)
{
    if (abs(pow(x, n) / factorial(n)) < pow(10, -6) || abs(pow(x, n) / factorial(n)) == pow(10, -6)) { return b; }
    else return b = (pow(x, n) / factorial(n)) + series(x, n + 1, b);
}

int main()
{
    float x;
    cout << "Enter x: "<<endl;
    cin >> x;
    cout << "E^x = " << series(x,0,0);
    system("pause");
    return 0;
}

Он работает нормально, когда abs(x) < 2, но когда abs(x) >= 2, появляется эта ошибка:

Необработанное исключение в 0x00F02539 в файле 33b.exe: 0xC00000FD: переполнение стека (параметры: 0x00000001, 0x00F22FF8). произошло

Я хочу знать, почему это происходит и как я могу это исправить?

2 ответа

Решение

Ваша проблема - слишком глубокая рекурсия. Рассмотрим цикл вместо этого.

float series(float x)
{
    const float epsilon = 1e-6f;
    double error = 1;
    double res = 1.f;
    int iter = 1;
    while (abs(error) > epsilon) {
        error *= (x / iter++);
        res += error;
        cout << error << endl;
    }
    return res;
}

int main()
{
    cout << "E^x = " << series(3);
    system("pause");
    return 0;
}

Чтобы быть яснее о том, что происходит:

Когда вы вызываете функцию внутри другой функции, контекст родительской функции сохраняется, чтобы освободить место для нового контекста. Когда вы начинаете миллионы, стек памяти, отвечающий за сохранение этого контекста, переполнен и переполнен.

Это переполнение стека.

 #include <iostream>
 #include <cmath>
 #include <cstdlib>
 using namespace std;
 int factorial[200];
 int Factorial(int a)
 {    if(a>0){
     factorial[a]=a * factorial[a-1];
         return factorial[a];
    }
    else
    factorial[a]=1;
    return 1;

 }

 double series(double x, int n, double b)
 {   double temp=(abs(pow(x, n)) / Factorial(n));
     if (temp <= 0.000001) { return b; }
     else return (temp + series(x, n + 1, b));
 }

 int main()
 {
     float x;
     cout << "Enter x: "<<endl;
     cin >> x;
     cout << "E^x = " << series(x,0,0);
     system("pause");
     return 0;
 }

ммм это решение работает. все, что я сделал, я взял ваш код, убрав abs(pow(x, n) / factorial(n)), где бы он ни повторялся, и инициализировал новую переменную temp. тогда вместо <|| == вы можете прямо поставить <=. и вместо того, чтобы вызывать функцию для вычисления.000001 каждый раз, когда вы можете просто указать это значение, чтобы еще больше сократить время. однако я считаю, что причина, по которой код может не сработать, - слишком большая рекурсия. поэтому для факториалов я использовал динамическое программирование, чтобы уменьшить его сложность. приведенный выше код работает отлично.

Другие вопросы по тегам