Разные значения функции в разных компиляторах
Есть программа, которая вычисляет значение функции на отрезке [-1; 1] поделенном на n равных(подается в stdin) ln(2+x) и значение этой же функции по ряду Тейлора: ln2 + x/2 - x^2/2^3 +...+(-1)^(n-1) * (x^n/(n*2^n))).
Очень странное поведение, компилирую в Clion при n = 10 выводит-
5| -0.000000 0.693147 40378677826926566000000000000...
компилирую в Ubuntu терминале при n = 10 выводит- 5| -0.000000 0.693147 0.000000
Затем компилирую в Clion при n = 100 выводит-
50| 0.000000 0.693147 0.693147
(это правильный ответ, так как значения совпадают)
НО! компилирую в Ubuntu и выводит -
50| 0.000000 0.693147 0.000000
Помогите понять, в чем проблема такого отличия? И как сделать чтобы при нулевом значении x выводило правильный ответ(при всех остальных значениях вывод в ubuntu и clion совпадает)
#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;
};
int oddEven(unsigned p)
{
return (p % 2 == 0) ? 1 : -1;
}
double f(unsigned p, double x)
{
double y = log(2);
for (unsigned i = 0; i <= p; ++i) {
y += (oddEven(i) * pow(x, i + 1)) / ((i + 1) * pow(2, i + 1));
}
return y;
}
double g(double x)
{
return log(2 + 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 %10lf %10lf\n", i, x, real_f(x), points[i].y);
}
}
int main()
{
unsigned n;
double a = -1, b = 1;
scanf("%u", &n);
TaylorCalculation(n, a, b, f, g);
}
Ответы (1 шт):
"Да понять-то его, надежа-царь, немудрено..." (с)
Смотрим комментарии, помня, что x==0, и вначале p == 0.
double f(unsigned p, double x)
{
double y = log(2);
// Этот цикл выполняется 1 раз, и ничего не прибавляет к y
// для указанных x и p равных 0
for (unsigned i = 0; i <= p; ++i) {
y += (oddEven(i) * pow(x, i + 1)) / ((i + 1) * pow(2, i + 1));
}
return y; // возвращает log(2)
}
Итак, и real_f(0), и taylor_f(p, 0) сразу возвращают одинаковое значение - log(2).
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;
}
}
// И когда дело доходит до вывода, выводится неприсвоенное значение.
// И самое интересное - НЕИНИЦИАЛИЗИРОВАННОЕ!!
// Т.е. где-то - 0, где-то - какой-то странный мусор...
printf("%d| %lf %10lf %10lf\n", i, x, real_f(x), points[i].y);
Все понятно?