Консультация № 177232
14.03.2010, 01:46
0.00 руб.
0 13 1
Здравствуйте, Ув. эксперты!
Задача:
Вычислить значение функции y, развив функцию ln(x) в ряд Тейлора. Аргумент х изменяется от -1 до 3 с шагом 0.5. Определить погрешность.
Y=
ln(x)+ln(x/2) 0<x<=2
ln(x/2-1) x>=2

Код моей программы во вложении.
Помогите, пожалуйста, отладить код...убрать ошибки, неточности и т.д.
Только начинаю изучать язык...вся надежда на вас...
Буду благодарна любой помощи!!!


Приложение:
Код:

#include <stdio.h>
#include <conio.h>
#include <math.h>


double logon(float x)
{
float sum=x-1; //сумма членов ряда
int i=1; //знаменатель элемента ряда
float t=0.001; //точность вычисления
float member=x-1; //текущий элемент ряда
while (member>t) //пока текущий элемент превышает точность рассчетов
{ member=member*(-(x-1)/i); //текущий элемент за формулой Тейлора
sum+=member; // сумма
i++; } //переход к новому елементу ряда
return sum;
}
void main (void)
{
float y, //виражение за формулой Тейлора
st, //значение стандартной функции log
x, //аргумент функции
xn, xk, //начальное, конечное значение аргумента
xs, err; //шаг изенения аргумента и погрешность
printf("\n input xn, xk, xs (-1 3 0.5)\n");
scanf("%f%f%f", &xn, &xk, &xs);
puts("===================================================");
printf(" x y standart error \n");
puts("===================================================");
for ( x=xn;x<=xk;x+=xs) //цикл перебора значений аргумента функции
{ if (0<=x<=2) //проверка условий вибора рассчетной функции
{ y=logon(x)–logon(x/2); //определение функции за формулой Тейлора
st=log(exp(x)) – log(exp(x/2)); //определение функции за стандартною формулою
err=st–y; //расхождение между точним и приближенным значениями функции
}
else if (x>=2)
{ y=logon(x/2-1);
st=log(exp(x/2-1));
err=st–y;
}
printf (" %f %f %f %f \n", x, y, st, err);
}
}

Обсуждение

Неизвестный
14.03.2010, 07:36
общий
При беглом просмотре обнаружил несколько ошибок:
1. log(x) не определена при x<=0, поэтому надо вставить проверку и возвращать NaN - Not A Number.
2. Формула Тейлора реализована неправильно. У Вас log(1+x)=Sum(x^n/n!), а должен быть Sum(x^n/n). Правильный код цикла: member*=x-1; sum+=member/i;
3. В main() ошибка в условном операторе. В C++ надо писать if(0<=x && x<=2)
4. В main() ошибка при вычислении результата: должно быть не st=log(exp(x)) – log(exp(x/2)); а st=log(x) – log(x/2);
давно
Академик
20764
1861
14.03.2010, 11:07
общий
Помимо того, на что указал Воробьёв Алексей Викторович, есть ещё одна принципиальная проблема - ряд Тейлора для логарифма даже там, где он сходится (0..2), сходится крайне медленно, и за счёт накопления ошибок вы получите полную ерунду, даже с long double. Вообще суммировать ряды, даже хорошо сходящиеся - дело опасное.

Получается, что заданная вам задача неразрешима принципиально.
Неизвестный
14.03.2010, 11:18
общий
Вот вроде бы учла все замечания, посмотрите, пожалуйста, что еще тут не так…

Код:
#include <stdio.h> 
#include <conio.h>
#include <math.h>


double logon(float x)
{
float sum=x-1;
int i=1;
float t=0.001;
float member=x-1;
while (member>t)
{ member=member*(x-1);
sum+=member/i;
i++; }
return sum;
}
void main (void)
{
float y,
st,
x,
xn, xk,
xs, err;
int flag=0;
printf("\n input xn, xk, xs (-1 3 0.5)\n");
scanf("%f%f%f", &xn, &xk, &xs);
puts("===================================================");
printf(" x y standart error \n");
puts("===================================================");
for ( x=xn;x<=xk;x+=xs)
{ if (0<=x && x<=2)
{ y=logon(x)–logon(x/2);
st=log(x) – log(x/2);;
err=st–y;
}
else if (x>=2)
{ y=logon(x/2-1);
st=log(x/2-1);
err=st–y;
}
else if (x<=0) flag =1;
if ( flag==0)
printf (" %f %f %f %f \n", x, y, st, err);
else printf (" %f not define \n", x );
}
}
Неизвестный
14.03.2010, 11:21
общий
Хватов Сергей, у меня пока сам код еще не компилируется...а с результатом уже потом что-то придумаю)
давно
Академик
20764
1861
14.03.2010, 11:40
общий
Gorlova:
Цитата: 324445
у меня пока сам код еще не компилируется

Когда код не компилируется, компилятор сообщает, где и что ему не нравится. Правда, не всегда его сообщения понятны, но если так, то процитируйте здесь его сообщения.
Неизвестный
14.03.2010, 13:24
общий
Цитирую ошибки

1) error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "–logon"
2) error C3861: –logon: идентификатор не найден
3) error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "–"
4) error C2065: –: необъявленный идентификатор
5) error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "log"
6) error C2065: st–y: необъявленный идентификатор
7) error C2065: st–y: необъявленный идентификатор
Неизвестный
14.03.2010, 13:36
общий
float logon(float x) //Возвращать double не имеет смысла, если расчеты происходят с float. Никакого выигрыша в точности это не даст. Или здесь float, или переменные - double
{
float sum=x-1;
int i=2; //с двойки
float t=0.001;
float member=x-1;
while (fabs(member)>t) //сдесь было неправильное условие завершения цикла
{ member=member*(-(x-1)*(i-1)/i); //текущий элемент за формулой Тейлора
sum+=member;
i++; }
return sum;
}
Неизвестный
14.03.2010, 13:44
общий
В тексте вместо минуса (err=st-y и т.д.) стоит тире. Это другой символ, компилятору не все равно.
Неизвестный
14.03.2010, 17:06
общий
Вот код уже рабочей моей программы
Код:
#include <stdio.h> 
#include <conio.h>
#include <math.h>


float logon(float x)
{
float sum=x-1;
int i=2;
float t=0.001;
float member=x-1;
while (fabs(member)>t)

{ member=member*(-(x-1)*(i-1)/i);
sum+=member;
i++; }
return sum;
}
void main (void)
{
float y,
st,
x,
xn, xk,
xs, err;
int flag=0;
printf("\n input xn, xk, xs (-1 3 0.5)\n");
scanf("%f%f%f", &xn, &xk, &xs);
puts("===================================================");
printf(" x y standart error \n");
puts("===================================================");
for ( x=xn;x<=xk;x+=xs)
{ if (0<=x && x<=2)
{ y=logon(x)-logon(x/2);
st=log(x) - log(x/2);
err=st-y;
}
else if (x>=2)
{ y=logon(x/2-1);
st=log(x/2-1);
err=st-y;
}
else if (x<=0) flag =1;
if ( flag==0)
printf (" %f %f %f %f \n", x, y, st, err);
else printf (" %f not define \n", x );
}
}



Подскажите, пожалуйста, правильно ли записана проверка для функции - при x<=0 функция не поределена ?
Почему тогда при заданных значениях (-1 3 0.5) везде выводится сообщение not define...
Спасибо!
Неизвестный
14.03.2010, 17:52
общий
for ( x=xn;x<=xk;x+=xs)
{
flag = 0; //сбрасываем значение переменой на каждой итерации
if (0<x && x<=2) //здесь интервал (0; 2]
{ y=logon(x)-logon(x/2);
st=log(x) - log(x/2);
err=st-y;
}
else if (x>=2)
{ y=logon(x/2-1);
st=log(x/2-1);
err=st-y;
}
else if (x<=0) flag =1;
if ( flag==0)
printf (" %f %f %f %f \n", x, y, st, err);
else printf (" %f not define \n", x );
}
Неизвестный
14.03.2010, 18:12
общий
Barney, даже не знаю, что сказать...да что тут говорить...СПАСИБО БОЛЬШОЕ!!!
Неизвестный
14.03.2010, 21:55
общий
Barney:
Воробьёв Алексей Викторович:
Оформите свои замечания как ответы, они достаточно полезны.
Неизвестный
18.03.2010, 22:16
общий
это ответ
Здравствуйте, Gorlova.
Взято из ответов в минифоруме Воробьёва Алексея Викторовича и Barney.
Ошибки в коде:
1. log(x) не определена при x<=0, поэтому надо вставить проверку и возвращать NaN - Not A Number.
2. Формула Тейлора реализована неправильно. У Вас log(1+x)=Sum(x^n/n!), а должен быть Sum(x^n/n). Правильный код цикла: member*=x-1; sum+=member/i;
3. В main() ошибка в условном операторе. В C++ надо писать if(0<=x && x<=2)
4. В main() ошибка при вычислении результата: должно быть не st=log(exp(x)) – log(exp(x/2)); а st=log(x) – log(x/2);
Исправленная функция:
Код:
float logon(float x) //Возвращать double не имеет смысла, если расчеты происходят с float. Никакого выигрыша в точности это не даст. Или здесь float, или переменные - double
{
float sum=x-1;
int i=2; //с двойки
float t=0.001;
float member=x-1;
while (fabs(member)>t) //сдесь было неправильное условие завершения цикла
{ member=member*(-(x-1)*(i-1)/i); //текущий элемент за формулой Тейлора
sum+=member;
i++; }
return sum;
}

Исправленный цикл:
Код:
for ( x=xn;x<=xk;x+=xs)
{
flag = 0; //сбрасываем значение переменой на каждой итерации
if (0<x && x<=2) //здесь интервал (0; 2]
{ y=logon(x)-logon(x/2);
st=log(x) - log(x/2);
err=st-y;
}
else if (x>2)
{ y=logon(x/2-1);
st=log(x/2-1);
err=st-y;
}
else flag =1;
if ( flag==0)
printf (" %f %f %f %f \n", x, y, st, err);
else printf (" %f not define \n", x );
}
Форма ответа