Можете ли вы дать мне совет о точности вычисления ряда Тейлора для экспоненты? У нас есть степень экспоненты и показатель точности, рассчитываемый как вводимые данные. Мы должны получить расчетное число с заданной точностью в качестве выходных данных. Я написал программу, но когда я вычисляю ответ и сравниваю его с ответом встроенной функции, он имеет отличия. Можете ли вы посоветовать мне, как я могу уничтожить разницу между ответами? формула расчета показателя
#include "stdafx.h"#include "iostream"#include <math.h>
#include <Windows.h>
#include <stdlib.h>
using namespace std;
int Factorial(int n);
double Taylor(double x, int q);
int main()
{
double res = 0;
int q = 0;
double number = 0;
cout << "Enter positive number" << "\n";
cin >> number;
cout << "Enter rounding error (precision)" << "\n";
cin >> q;
cout << "\n" << "\n";
res = Taylor(number, q);
cout << "Answer by Taylor : " << res;
cout << "Answer by embedded function: " << exp(number);
Sleep(25000);
return 0;
}
int Factorial(int n) {
int res = 1;
int i = 2;
if (n == 1 || n == 0)
return 1;
else
{
while (i <= n)
{
res *= i;
i++;
}
return res;
}
}
double Taylor(double x, int q) {
double res = 1;
double res1 = 0;
int i =1;
while (i)
{
res += (pow(x, i) / Factorial(i));
if (int(res*pow(10, q)) < (res*pow(10, q)))
{//rounding res below
if ( ( int (res * pow(10,q+1)) - int(res*pow(10, q))) <5 )
res1 = (int(res*pow(10, q))) * pow(10, (-q));
else
res1 = (int(res*pow(10, q))) * pow(10, (-q)) + pow(10,-q);
return res1;
}
i++;
}}
В вашем коде есть две проблемы. Во-первых, факториал очень склонен к переполнению. На самом деле я не знаю, когда происходит переполнение для int
факториалы, но я помню что например на обычных карманных калькуляторах x!
переполняется уже для x==70
, Вероятно, вам не нужны такие высокие факториалы, но все же лучше избегать этой проблемы с самого начала. Если вы посмотрите на исправление, которое нужно добавить на каждом шаге: x^i / i!
(математическая запись), то вы заметите, что это значение на самом деле намного меньше, чем x^i
или же i!
соответственно. Также вы можете легко вычислить значение из предыдущего, просто умножив его на x/i
,
Во-вторых, я не понимаю ваших расчетов для точности. Может быть, это правильно, но, честно говоря, для меня это выглядит слишком сложно, чтобы даже попытаться понять это;).
Вот как вы можете получить правильное значение:
#include <iostream>
#include <cmath>
struct taylor_result {
int iterations;
double value;
taylor_result() : iterations(0),value(0) {}
};
taylor_result taylor(double x,double eps = 1e-8){
taylor_result res;
double accu = 1; // calculate only the correction
// but not its individual terms
while(accu > eps){
res.value += accu;
res.iterations++;
accu *= (x / (res.iterations));
}
return res;
}
int main() {
std::cout << taylor(3.0).value << "\n";
std::cout << exp(3.0) << "\n";
}
Обратите внимание, что я использовал структуру для возврата результата, так как вы должны обратить внимание на количество необходимых итераций.
PS: смотри Вот для модифицированного кода, который позволяет использовать уже вычисленный результат, чтобы продолжить серию для большей точности. Imho хорошее решение должно также предоставить способ установить ограничение на количество итераций, но это я оставляю вам для реализации;)
Других решений пока нет …