Ряд Тейлора функции e^x

Дано число х. Вам нужно рассчитать сумму ряда Тейлора e ^ x.

e^x = 1 + x + x^2/2! + x^3/3! + ...

Вычисляйте сумму до тех пор, пока общее число не станет меньше или равно 10 ^ (-9).

Ниже приведено мое решение, но оно неверно для чисел x‹0. У вас есть идеи, как исправить это, чтобы работать с отрицательными числами.

    int x,i,n;
    long long fact; //fact needs to be double
    double sum=0,k=1;
    scanf("%d",&x);
            i=0; sum=0; k=1;
                while (fabs(k)>=1.0E-9) {
                    fact=1;
                    for (int j=1;j<=i;++j)
                        fact*=j;
                    k=pow(x,i)/fact;
                    sum+=k;
                    ++i;
                }
    printf("%lf\n",sum);

person dreamer    schedule 25.10.2015    source источник
comment
какие типы этих переменных... если вы не дали нам достаточно для компиляции, вы не дали нам достаточно для отладки   -  person Grady Player    schedule 25.10.2015
comment
Извините, я просто добавил.   -  person dreamer    schedule 25.10.2015
comment
Да спасибо. Я забыл об этом. Но результат снова неверный. Например, если выход x=-2 равен 0,33333, он должен быть равен 0,13533, для x=-4 сумма=0,192240 он должен быть равен 0,018316 и т. д.   -  person dreamer    schedule 25.10.2015
comment
Вы используете пространство имен std? Вы включили cmath или math.h? Также было бы хорошо, если бы вы явно преобразовали свои типы данных   -  person FreelanceConsultant    schedule 25.10.2015
comment
fabs, abs с плавающей запятой, мой плохой.   -  person user3528438    schedule 25.10.2015
comment
@ user3728501: это код C, а не код C++   -  person Basile Starynkevitch    schedule 25.10.2015
comment
ideone.com/PyGPO6   -  person user3528438    schedule 25.10.2015
comment
Я просто изменил тип факта на двойной, и он работает.   -  person dreamer    schedule 25.10.2015
comment
@BasileStarynkevitch Point остается в силе - не используйте пространство имен и включайте только math.h   -  person FreelanceConsultant    schedule 26.10.2015


Ответы (3)


Вы не должны использовать функцию pow для возведения числа (возможно, отрицательного) в целую степень. Вместо этого используйте повторное умножение, как при вычислении факториала.

Заметьте также, что вы можете сохранить последние вычисленные значения $n!$ и $x^k$, чтобы получить $(n+1)!$ и $x^{k+1}$ одним умножением.

person Emanuele Paolini    schedule 25.10.2015

Ваша проблема в том, что ваши факторные вычисления переполняются и становятся мусором. После этого ваш ith срок больше не уменьшается и дает совершенно неправильные результаты.

После 20 итераций 64-битное число не может содержать значение 20!. См.: http://www.wolframalpha.com/input/?i=21%21%2F2%5E64

Если x^n/n! не уступает вашему порогу (1e-9) при n=20, то ваше вычисление n! приведет к переполнению даже 64-битного целого числа. Когда это произойдет, вы получите значение n! по модулю 2^63 (я упрощаю, потому что вы не использовали целое число без знака, и вместо этого вы получите случайное отрицательное значение, но принцип остается). Эти значения могут быть очень низкими, а не очень высокими. И это приведет к тому, что ваш x^n/n! станет больше, а не меньше.

person fjardon    schedule 25.10.2015
comment
Я не уверен, можете ли вы объяснить лучше. Я обнаружил, что проблема заключается в типе факта, когда я изменил факт на двойной, он хорошо работает для небольшого числа (это то, что мне нужно). Я не знаю почему. Я бы попросил вас лучше объяснить свой ответ, потому что он кажется интересным, я согласен, что решение имеет переполнение, но ничего существенного. - person dreamer; 25.10.2015
comment
Да, я согласен. Спасибо за объяснение. Но я не могу использовать unsigned int, потому что x может быть отрицательным. - person dreamer; 25.10.2015
comment
@dreamer Использование unsigned не решит проблему. Он просто будет давать точные модули (mod 2 ^ 63) вместо двух дополнительных интерпретаций модуля. Но проблема останется. Если это объяснение помогло вам, не забудьте проголосовать. - person fjardon; 26.10.2015

факт должен быть двойным, он не может быть длинным из-за делений.

person dreamer    schedule 25.10.2015