Вычисление значений функции с помощью ряда Тейлора на Си
Задание заключается в том, чтобы посчитать значение функции ln((1+x)/(1-x)) с помощью заданной функции и ряда Тейлора для нее 2(x/1 + x^3/3 + ... + x^(2n+1) / 2n + 1) на определенном отрезке a b, разбитом на n частей(n принимается с stdin), сравнить их. Моя программа неправильно считает значение функции с помощью ряда Тейлора на самой первой итерации(выдает какое-то нереальное значение), а на других итерациях считает все правильно.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
double macheps()
{
double e = 1.0;
while (1.0 + e / 2.0 > 1.0)
e /= 2.0;
return e;
}
struct Point
{
double x;
double y;
};
double f(unsigned p, double x)
{
double y = 0.;
for(unsigned i = 0; i <= p; ++i) {
y += (2 * (pow(x , 2 * i + 1) / (2 * i + 1)));
}
return y;
}
double g(double x)
{
return log((1 + x) / (1 - x));
}
void TaylorCalculation(unsigned iterationCount, double a, double b, double (*taylor_f)(unsigned, double), double (*real_f)(double))
{
double step = ( b - a ) / iterationCount;
struct Point* points = (struct Point*)malloc(sizeof(struct Point) * iterationCount);
double eps = macheps();
double x = a;
for(unsigned i = 0; i < iterationCount; ++i, x+=step) {
unsigned p = 0;
while(fabs(real_f(x) - taylor_f(p, x)) > eps * 100)
{
points[i].x = x;
points[i].y = taylor_f(p, x);
++p;
if(p >= 100) {
break;
}
}
printf("%d| %lf %lf %lf\n", i, x, real_f(x), points[i].y);
}
}
int main()
{
unsigned n;
double a = 0., b = 0.5;
scanf("%u", &n);
TaylorCalculation(n, a, b, f, g);
}
Например n = 10, вывод таков:
0| 0.000000 0.000000 139105536617883030000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000.000000
1| 0.050000 0.100083 0.100083
2| 0.100000 0.200671 0.200671
3| 0.150000 0.302281 0.302281
4| 0.200000 0.405465 0.405465
5| 0.250000 0.510826 0.510826
6| 0.300000 0.619039 0.619039
7| 0.350000 0.730888 0.730888
8| 0.400000 0.847298 0.847298
9| 0.450000 0.969401 0.969401
Как можем заметить, на 1-9 итерации все верно, а на 0 бред...
Ответы (1 шт):
Запутанная ошибка, но как всегда классика с вещественной арифметикой:).
Вначале поймем, что именно выводится. А это point[0].y. Смотрим выше и понимаем, что оно должно быть равно x, а также a на первой (нулевой) итерации. Я вначале даже начал на printf грешить. Но потом посмотрел в условие в while
fabs(real_f(x) - taylor_f(p, x)) > eps * 100
А что, если это условие не выполняется? тогда point[0].y будет не инициализировано и там может быть все, что угодно. Например, такое большое число. Как проверить? инициализировать нулем перед while.
Но почему же условие не выполнилось? это уже сложнее. В моих оценках все три части этого выражения равны нулю или очень близки к этому.
eps => 1.0 + e / 2.0 > 1.0 => e/2.0 > 0 - это число все таки скорее всего будет такое, что после деления на два будет ноль (выйдет за пределы double), но все таки какое то маленькое. Два других числа равны нулю. И теперь стает очевидно, что условие ложно. И на том же ideone можно это проверить - https://ideone.com/nN8iiZ
Почему же до этого не было видно? переменная не инициализирована. И она может быть какой угодно, например нулем. А может и больше.