Технический форум

Технический форум (http://www.tehnari.ru/)
-   Помощь студентам (http://www.tehnari.ru/f41/)
-   -   Программа почти работает (http://www.tehnari.ru/f41/t80986/)

Sorento 23.11.2012 20:25

Программа почти работает
 
Вложений: 3
На фотографиях задание.

вот код:
Код:

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

 
long double fact(int N)
{
    if(N < 0) // åñëè ïîëüçîâàòåëü ââåë îòðèöàòåëüíîå ÷èñëî
        return 0; // âîçâðàùàåì íîëü
    if (N == 0) // åñëè ïîëüçîâàòåëü ââåë íîëü,
        return 1; // âîçâðàùàåì ôàêòîðèàë îò íóëÿ - íå óäèâëÿåòåñü, íî ýòî 1 =)
    else // Âî âñåõ îñòàëüíûõ ñëó÷àÿõ
        return N * fact(N - 1); // äåëàåì ðåêóðñèþ.
}

int main()
{
      double n, b, xn, xk, sh, t,  x, sum, w, f;
      int i;
      //char string[105];
      char Y,N;
     
      a1: while(1)
      { 
      printf("Vvedite x nachal'noe, x konechnoe, sdvig, shag, tochnost'\n");     
      scanf("%lf%lf%lf%lf%lf", &xn,&xk,&b,&sh,&t);
      {
             
           
printf("+---------------------------------------+\n");
printf("¦    X    ¦cos(x+b) ¦ Function¦    N    ¦\n");
printf("¦---------+---------+---------+---------¦\n");
      for(x=xn;x<xk+sh/8;x+=sh)
      {
    sum=0.0;
    n=0.0;
    while(fabs(pow(x, n)*cos(b+3.14*n/2))/fact(n)>t)
    {
                      n++;
                      }
                      for(i = 0.0; i<n; i++)
                      sum+=pow(x, i)*cos(b+M_PI*i/2)/fact(i);
   
     
printf("¦ %6.2f  ¦ %6.3f  ¦ %6.3f  ¦  %6g  ¦\n", x, cos(x+b), sum, n);
      }
printf("+---------------------------------------+\n");


a2: printf("Prodolzhit' vichysleniya? (Y/N)\n");




}
if(getche()=='Y') goto a1;
if(getche()=='N') return 0;
else goto a2;
}
return 0;
}



Не пойму почему после 35-ого элемента счет через ряд сбивается, и начинают вываливаться большие числа.

Vladimir_S 23.11.2012 20:55

Цитата:

Сообщение от Sorento (Сообщение 823282)
Не пойму почему после 35-ого элемента счет через ряд сбивается, и начинают вываливаться большие числа.

Гм, на первый взгляд вроде всё правильно. К сожалению, сам на СИ не пишу, поэтому, если никто не поможет раньше, перепишу Вашу программу на Паскаль и погоняю. Но это будет не сию секунду. Может быть, завтра утром.

Sorento 23.11.2012 21:53

Буду благодарен. Программирование начал изучать только в универе. Очень тяжко получается:)Мне не совсем к спеху) Буду очень благодарен!:)

Vladimir_S 23.11.2012 23:44

Вложений: 1
Ну вот, нарисовал. Не без внутренней борьбы, поскольку полностью разделяю мнение, что все эти переходы по меткам (GoTo) подлежат неукоснительному изгнанию, чего Вам на будущее советую. Дурной стиль и "лапша" в итоге. Ну ладно, это лирика. Вот что получилось:
Код:

Var
 b,xn,xk,x,sh,sum,t:real;
 n,i:Integer;
 YN:Char;
 Label a1,a2;

Function fact(M:Integer):Extended;
begin
 if M=0 then fact:=1 else fact:=M*fact(M-1);
end;

Begin
 a1:
 Writeln('Vvedite x nachal"noe, x konechnoe, sdvig, shag, tochnost');
 Readln(xn,xk,b,sh,t);
 Writeln('+---------------------------------------+');
 Writeln('    X    cos(x+b)  Function    N      ');
 Writeln('+--------+---------+---------+----------+');
 x:=xn;
 Repeat
  sum:=0;
  n:=0;
  While abs(Exp(n*Ln(x))*cos(b+3.14*n/2))/fact(n)>t do n:=n+1;
  For i:=0 to n do
  sum:=sum+Exp(i*Ln(x))*cos(b+Pi*i/2)/fact(i);
  Writeln(x:6:2,Cos(x+b):11:3,sum:11:3,n:8);
  x:=x+sh;
 Until x>xk+sh/8;
 Writeln('+--------+---------+---------+----------+');
 a2:
 Write('Prodolzit vychisleniya (Y/N)? ');
 Readln(YN);
 If YN='Y' then GoTo a1
 else
 If YN='N' then Halt(0)
 else GoTo a2;
End.

Постарался максимально точно воспроизвести сишный исходник. Запускал, гонял - хоть застрелись, никаких ошибок. А потому
Цитата:

Сообщение от Sorento (Сообщение 823282)
Не пойму почему после 35-ого элемента счет через ряд сбивается, и начинают вываливаться большие числа.

вот с этого места - подробнее. Какие данные вводите? Что за "35-й элемент"? Не очень ясно.

Sorento 23.11.2012 23:57

Попробуйте использовать х от 1 до 100

Sorento 23.11.2012 23:59

Вложений: 1
Я вот про это

Vladimir_S 24.11.2012 12:43

Вложений: 1
Цитата:

Сообщение от Sorento (Сообщение 823438)
Я вот про это

Понятно. У меня тоже получается "это":
Вложение 106579
Причем никакими ухищрениями "это" не одолевается. А пробовал я многое: переход на рекуррентный способ вычисления слагаемых (тогда можно исключить вычисление факториала в явном виде), исключения периодов косинуса, так, чтобы привести аргумент в диапазон -2π..2π - тщетно! Похоже, тут мы просто упёрлись в ограничения разрядных сеток или, скорее, адресации цифровых ЭВМ, то есть, хотя формально разложение функции Cos(x+b) работает для |x|<∞, реально начиная с нескольких десятков компьютер выдает всякую чушь.
Подождем, может быть профессионалы подскажут что-нибудь в этом плане: я-то любитель-самоучка. А пока просто ограничьте диапазон аргументов, скажем, x+b<10.

Sorento 25.11.2012 02:45

Я так понимаю идей никаких?(

Vladimir_S 25.11.2012 10:14

Вложений: 2
Цитата:

Сообщение от Sorento (Сообщение 823876)
Я так понимаю идей никаких?(

Вы неверно понимаете.
Суть проблемы в том, что следует представлять себе ответы на вопросы о применимости разложения функций в ряд Тейлора и об условиях достоверности аппроксимации значения функции конечной суммой членов такого ряда.
Дело в том, что разложение в ряд Тейлора ведется всегда в окрестности некоей центральной точки, и чем ближе аргумент к этой точке, тем точнее приближение суммой конечного числа членов ряда, или тем меньше членов ряда нужно учесть, чтобы достичь требуемой точности. Если же мы уйдем далеко от центра, то тут возможны "сюрпризы".
Рассмотрим наш случай.
Здесь разложение ведется в окрестности х=0. И действительно, для небольших значений аргумента, в пределах одного-двух десятков, всё нормально. А вот дальше... Дальше, для больших аргументов, начинается серьёзная конкуренция между степенной функцией в числителе и факториалом в знаменателе, благодаря чему сначала модули слагаемых членов ряда в зависимости от номера начинают возрастать до огромных (порядка 10^20-10^30, ^ - возведение в степень) значений, а затем спадают, выходя практически на "плато". То же самое происходит и с суммой, только она "застывает" на значениях порядка 10^10-10^20, что мы и видим. Возникает вопрос - а почему же тогда в справочниках область применимости разложения указана, как |x|<∞? Всё правильно. Если Вы вообразите ЭВМ с бесконечноёмкой разрядной сеткой и просуммируете миллионы-миллиарды-триллионы-квинтильоны и т.д. членов ряда, то в конце концов придёте к нужному значению Вашего косинуса.
Итог: повторяю - ограничьте диапазон значений аргумента. Это всё.

Приложенные файлы иллюстрируют вышеприведенный анализ и содержат расчеты для малых и больших аргументов (значения - в первой строке файла). Колонка А (вторая) - это значения члена ряда под номером n.

Sorento 25.11.2012 11:07

Вложений: 1
А нельзя ли факториал задать без функции??
Скажем на основе вот этого примера:
вариант 2


Часовой пояс GMT +4, время: 13:51.

Powered by vBulletin® Version 4.5.3
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.