• Добро пожаловать на компьютерный форум Tehnari.ru. Здесь разбираемся с проблемами ПК и ноутбуков: Windows, драйверы, «железо», сборка и апгрейд, софт и безопасность. Форум работает много лет, сейчас он переехал на новый движок, но старые темы и аккаунты мы постарались сохранить максимально аккуратно.

    Форум не связан с магазинами и сервисами – мы ничего не продаём и не даём «рекламу под видом совета». Отвечают обычные участники и модераторы, которые следят за порядком и качеством подсказок.

    Если вы у нас впервые, загляните на страницу о форуме и правила – там коротко описано, как задать вопрос так, чтобы быстро получить ответ. Чтобы создавать темы и писать сообщения, сначала зарегистрируйтесь, а затем войдите под своим логином.

    Не знаете, с чего начать? Создайте тему с описанием проблемы – подскажем и при необходимости перенесём её в подходящий раздел.
    Задать вопрос Новые сообщения Как правильно спросить
    Если пришли по старой ссылке со старого Tehnari.ru – вы на нужном месте, просто продолжайте обсуждение.

Программа почти работает

  • Автор темы Автор темы Sorento
  • Дата начала Дата начала

Sorento

Новые
Регистрация
23 Ноя 2012
Сообщения
14
Реакции
0
Баллы
0
Программа почти работает

На фотографиях задание.

вот код:
Код:
#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-ого элемента счет через ряд сбивается, и начинают вываливаться большие числа.
 

Вложения

  • 5N7BPt1vup8.webp
    5N7BPt1vup8.webp
    39.1 KB · Просмотры: 65
  • I3641op9Jok.webp
    I3641op9Jok.webp
    65.7 KB · Просмотры: 56
  • jejXPIjhDKo.webp
    jejXPIjhDKo.webp
    54.2 KB · Просмотры: 62
Не пойму почему после 35-ого элемента счет через ряд сбивается, и начинают вываливаться большие числа.
Гм, на первый взгляд вроде всё правильно. К сожалению, сам на СИ не пишу, поэтому, если никто не поможет раньше, перепишу Вашу программу на Паскаль и погоняю. Но это будет не сию секунду. Может быть, завтра утром.
 
Буду благодарен. Программирование начал изучать только в универе. Очень тяжко получается:)Мне не совсем к спеху) Буду очень благодарен!:)
 
Ну вот, нарисовал. Не без внутренней борьбы, поскольку полностью разделяю мнение, что все эти переходы по меткам (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.
Постарался максимально точно воспроизвести сишный исходник. Запускал, гонял - хоть застрелись, никаких ошибок. А потому
Не пойму почему после 35-ого элемента счет через ряд сбивается, и начинают вываливаться большие числа.
вот с этого места - подробнее. Какие данные вводите? Что за "35-й элемент"? Не очень ясно.
 

Вложения

  • Sor_1.webp
    Sor_1.webp
    28.8 KB · Просмотры: 74
Попробуйте использовать х от 1 до 100
 
Я вот про это
 

Вложения

  • Снимок.webp
    Снимок.webp
    180.7 KB · Просмотры: 72
Понятно. У меня тоже получается "это":
Sor_2.webp
Причем никакими ухищрениями "это" не одолевается. А пробовал я многое: переход на рекуррентный способ вычисления слагаемых (тогда можно исключить вычисление факториала в явном виде), исключения периодов косинуса, так, чтобы привести аргумент в диапазон -2π..2π - тщетно! Похоже, тут мы просто упёрлись в ограничения разрядных сеток или, скорее, адресации цифровых ЭВМ, то есть, хотя формально разложение функции Cos(x+b) работает для |x|<∞, реально начиная с нескольких десятков компьютер выдает всякую чушь.
Подождем, может быть профессионалы подскажут что-нибудь в этом плане: я-то любитель-самоучка. А пока просто ограничьте диапазон аргументов, скажем, x+b<10.
 
Я так понимаю идей никаких?(
 
Я так понимаю идей никаких?(
Вы неверно понимаете.
Суть проблемы в том, что следует представлять себе ответы на вопросы о применимости разложения функций в ряд Тейлора и об условиях достоверности аппроксимации значения функции конечной суммой членов такого ряда.
Дело в том, что разложение в ряд Тейлора ведется всегда в окрестности некоей центральной точки, и чем ближе аргумент к этой точке, тем точнее приближение суммой конечного числа членов ряда, или тем меньше членов ряда нужно учесть, чтобы достичь требуемой точности. Если же мы уйдем далеко от центра, то тут возможны "сюрпризы".
Рассмотрим наш случай.
Здесь разложение ведется в окрестности х=0. И действительно, для небольших значений аргумента, в пределах одного-двух десятков, всё нормально. А вот дальше... Дальше, для больших аргументов, начинается серьёзная конкуренция между степенной функцией в числителе и факториалом в знаменателе, благодаря чему сначала модули слагаемых членов ряда в зависимости от номера начинают возрастать до огромных (порядка 10^20-10^30, ^ - возведение в степень) значений, а затем спадают, выходя практически на "плато". То же самое происходит и с суммой, только она "застывает" на значениях порядка 10^10-10^20, что мы и видим. Возникает вопрос - а почему же тогда в справочниках область применимости разложения указана, как |x|<∞? Всё правильно. Если Вы вообразите ЭВМ с бесконечноёмкой разрядной сеткой и просуммируете миллионы-миллиарды-триллионы-квинтильоны и т.д. членов ряда, то в конце концов придёте к нужному значению Вашего косинуса.
Итог: повторяю - ограничьте диапазон значений аргумента. Это всё.

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

Вложения

  • XXX_1.TXT
    XXX_1.TXT
    1.4 KB · Просмотры: 486
  • XXX_2.TXT
    XXX_2.TXT
    10.8 KB · Просмотры: 498
А нельзя ли факториал задать без функции??
Скажем на основе вот этого примера:
вариант 2
 

Вложения

  • IMG_20121022_154310.webp
    IMG_20121022_154310.webp
    126.2 KB · Просмотры: 42
А нельзя ли факториал задать без функции??
Можно. Вот вариант Вашей программы (увы, на Паскале) без явного задания факториала и явного использования возведения в степень. Но, повторяю, для больших аргументов это ровно ничего не меняет, ибо сходимость ряда в таком случае ужасающе медленная.

Код:
Var
 b,xn,xk,x,sh,sum,t,A:real;
 n:Integer;
 YN:Char;
 Label a1,a2;

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
  A:=Cos(b);
  sum:=Cos(b);
  n:=0;
  While abs(A)>t do
   begin
    n:=n+1;
    A:=A*x/n/Cos(b+Pi*(n-1)/2)*Cos(b+Pi*n/2);
    sum:=sum+A;
   end;
  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.
 
A*x/n/Cos(b+Pi*(n-1)/2)*Cos(b+Pi*n/2)
 
можно расшифровать?)
 
Назад
Сверху