Помощь - Поиск - Пользователи - Календарь
Полная версия: построение графика функции
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
yar11
program Grafik_funkcii;
uses crt,graph;
var
 {координаты графика функции}
 x,y,a,b:real;
 {Номера типа графического дрaйвера и номера графического режима}
 driver,mode:integer;
 {cx,cy - координаты центра системы координат на экране,
 mx,my - масштаб (количество пикселей на единицу),
 ex,ey - координаты точки графика в масштабе экрана}
 cx,cy,mx,my,ex,ey,n:integer;
 {Описание функции, график которой затем выводится на экран}
 function f(x:real):real;
   begin
            f:=sin(3*x)+cos(x)/exp(x)
    end;
     procedure DeleniyaX(a:real);
     var
     stroka:string;x,s:real;
     begin
     {Деления выставляются в 10-ти точках от -a до a c шагом s}
      x:=-a;s:=2*a/10;
      repeat
        ex:=trunc(cx+x*mx)-10;
        ey:=cy+5;
        str(x:3:1,stroka);
        outtextxy(ex,ey,stroka);
        x:=x+s;
      until x>a;
     end;
     procedure DeleniyaY(b:real);
      var
       stroka:string;y:real;s:integer;
        begin
        {Деления по оси Y выставляются в 10 точках от -b до b}
         s:=trunc((getmaxy-30)/10);ey:=getmaxy-30;
         repeat
           ex:=cx+5;
           y:=b-ey/my;
           str(y:3:1,stroka);
           if abs(y)>0.5 then outtextxy(ex,ey+5,stroka);
           ey:=ey-s;
         until ey<10;
        end;
        {Подпрограмма построения графика}
        procedure MyGrafik(a,b:real);
        {Процедура строит график от -a до a c шагом s}
         var p,n:integer;s,t:real;
             strx:string;
          begin
           {Положение начала координат на экране}
           cx:=trunc(getmaxx/2);cy:=trunc(getmaxy/2);
           {Цвета фона и текста}
           SetBkColor(yellow);SetColor(blue);
           line(10,cy,getmaxx-50,cy);{Ось X}
           {Стрелочка на оси X}
           line(getmaxx-60,cy-5,getmaxx-50,cy);
           line(getmaxx-60,cy+5,getmaxx-50,cy);
           line(cx,10,cx,getmaxy-20);  {Ось Y}
           {Рисование стрелочки на оси y}
           line(cx-5,20,cx,10);line(cx+5,20,cx,10);
           setcolor(magenta);
           {Подписи к осям}
           outtextxy(cx+10,10,'y');
           outtextxy(getmaxx-50,cy-10,'x');
           {Определение масштаба по осям X и Y исходя из того,
            что X от -a до a}
           mx:=trunc((getmaxx)/(2*a));
           {Y от -b до b}
           my:=trunc((getmaxy)/(2*b));
           {Вывод значений по оси X от -a до a}
           DeleniyaX(a);
           {Вывод значений по оси Y от -b до b}
           DeleniyaY(b);
           outtextxy(10,50,'График функции');
           {x меняется от -a до a c шагом s в n+1 точке}
           x:=-a;n:=500;s:=2*a/n;
           moveto(trunc(cx+x*mx),trunc(cy-f(x)*my));
           Repeat
            y:=f(x);
            ex:=trunc(cx+x*mx);
            ey:=trunc(cy-y*my);
            lineto(ex,ey);
            x:=x+s;
           Until ex>getmaxx-70;
          end;
 Begin
  clrscr;
  write('a=');readln(a);
  write('b=');readln(b);
  {Открытие графического режима}
  driver:=detect;
  initgraph(driver,mode,'d:\tp\bgi');
  {очистка экрана в графическом режиме}
  cleardevice;
  {выполнение процедуры вывода графика}
  MyGrafik(a,b);
  {задержка}
  repeat
  {до нажатия клавиши Enter}
  until keypressed;
 End.

это программа построения графика функции по точкам
почему-то она не работает при данной функции f:=sin(3*x)+cos(x)/exp(x)
при значениях b больше 19
пишет ошибку invalid floating point operation
может кто подскажет
volvo
Цитата
почему-то она не работает при данной функции f:=sin(3*x)+cos(x)/exp(x)
при значениях b больше 19
blink.gif
Задал в программе
a := 1; b := 25

все прекрасно отчертилось... Может, потому, что у меня ВСЕГДА используется сопроцессор? (я установил это в опциях IDE)
yar11
спасибо за совет
Возник вопрос: в каких все-таки случаях надо подключать сопроцессор
ведь в данном случае не используются типы переменных double, extended, single
klem4
А какже

 x,y,a,b:real;


?

cool.gif
yar11
Цитата
Эмуляция сопроцессора
Очень часто у многих возникает вопрос - почему при компиляции у меня возникает ошибка Error 116: Must be in 8087 mode to compile this.
Ответ: Вы используете один из следующих вещественных типов:
Single, Double, Extended, Comp
Для работы с этими типами, необходима эмуляция сопроцессора. Просто добавьте в начало программы директивы:
{$E+, $N+}

можетя что-то не так понял
видимо в моей проге {$N+} используется по какой-то другой причине
klem4
Цитата(FAQ)
{$N-} - Использование сопроцессора. (Глобальная директива). При указании режима {$N-} генерируется код для программного выполнения всех вещественных вычислений. При режиме {$N+} генерируется код для выполнения таких вычислений аппаратно с помощью сопроцессора.


Для корректной работы с числами с плавающей точкой нужна эта директива, сколько же можно обсуждать !
madpanda
Ребята у меня вот такая вот функция
y=2^x-5*cos(x)-3
Мне нужно построить по точкам.
Подойдет ли данная программа для моей функции???
Заранее спасибо.
P.S. В Паскале понимаю очень мало.
volvo
А заменить функцию на твою и попробовать МЫ должны? Почему не ТЫ?

Замени, и прогони программу. Заодно и расскажешь, работает или нет... Мне тоже интересно...
Сталкер
Можно ли создавать скрин графика с белым фоном. Если да, то как?
Добавил в приведённой выше программе setBkColor(white);
save_bmp(0, 0, getmaxx, getmaxy, 'screen.bmp', 1);
Не помогло no1.gif
volvo
Цитата(Сталкер @ 19.04.2007 19:48)
Можно ли создавать скрин графика с белым фоном.
И это можно...

Цитата(Сталкер @ 19.04.2007 19:48) *

Добавил в приведённой программе
setBkColor(white);
save_bmp(0, 0, getmaxx, getmaxy, 'screen.bmp', 1);
Не помогло no1.gif

Еще бы... Ты попробуй добавить:

setfillstyle(solidfill, white);
bar(0, 0, getmaxx, getmaxy);
...
save_bmp(0, 0, getmaxx, getmaxy, 'screen.bmp', 1);
Чувствуешь разницу?
Сталкер
Спасибо. yes2.gif Теперь можно экономить чёрный картридж. good.gif
зайка
люди помогите плиз, беру самую простую функцию y=x*x;
при любых а,b выдаёт ошибку вот в этом месте
 Repeat           
 y:=f(x);           
 ex:=trunc(cx+x*mx);           <=пишет что-то про точки
 ey:=trunc(cy-y*my);          
  lineto(ex,ey);          
  x:=x+s;           
Until ex>getmaxx-70;
.
volvo
Цитата
<=пишет что-то про точки
Что именно "про точки"? Я вот только что попробовал, мне ничего ни про какие точки не пишет (исправил только функцию F в программе, приведенной в первом посте, и задал A = 1, B = 10) - график построился и с подключенным сопроцессором, и без него (Турбо Паскаль 7).
зайка
пишет "invalid floating point operation"
и выставляет курсор в начало строки
"ey:=trunc(cy-y*my);" и попробовала поставить a=1 b=10
volvo
Во-первых, какой у тебя компилятор? А во-вторых, прикрепи-ка файл с программой (не надо весь текст копировать, именно прикрепи PAS-файл!!!) сюда, есть смутное подозрение...
зайка
я честно говоря не особо разбираюсь в компиляторахsad.gif
volvo
Угу yes2.gif ... Я так и думал:

Цитата
function f(x:real):real;
         begin
              y:=x*x;
         end;
Замени на
function f(x:real):real;
         begin
              f:=x*x; { <--- Внимательно - ты же должна вернуть результат ФУНКЦИИ }
         end;
зайка
Цитата(volvo @ 5.07.2008 1:39) *

Угу yes2.gif ... Я так и думал:

Замени на
function f(x:real):real;
         begin
              f:=x*x; { <--- Внимательно - ты же должна вернуть результат ФУНКЦИИ }
         end;


ой спасибо блин я тормоз ypriamii.gif !thanks.gif


вот смотри теперь я беру свою огромнейшую функцию 20й степени, которая при х=1 равна 1'200'000 с хвостиком, она мне строит график, но по бокам какие-то вертикальные полосы, при том чем больше значение ф-и тем их меньше. что это может быть?

слушай а можешь здесь ещё посмотреть задание функции?
пишет "stack overflow error" показывает ошибку у первой проц. степени

Добавлено через 17 мин.
вот здесь глянь плиз
volvo
Цитата
а можешь здесь ещё посмотреть задание функции?
Еще бы увидеть саму эту функцию, что именно ты пытаешься закодировать - непонятно. А Stack OverFlow у тебя - потому что бесконечная рекурсия:

...
for k:=0 to n do
  y:=y(x)+y1; { <--- Вот тут... }
...

Где-то стек должен переполниться? Вот в твоем случае он переполняется
Цитата
у первой проц. степени
.
зайка
Цитата(volvo @ 5.07.2008 12:26) *

Еще бы увидеть саму эту функцию, что именно ты пытаешься закодировать - непонятно. А Stack OverFlow у тебя - потому что бесконечная рекурсия:

в общем щас попытаюсь
F=10*суммa(от0до10)[[((-1)^k)*(19-k)!*((4*(x^2))^(10-k))]/[k!*(20-2*k)!]]
volvo
Другими словами:
F = 10 *
((-1)0 * 19! * (4*x2)10) / (0! * 20!) +
((-1)1 * 18! * (4*x2)9) / (1! * 18!) +
((-1)2 * 17! * (4*x2)8) / (2! * 16!) +
((-1)3 * 16! * (4*x2)7) / (3! * 14!) +
((-1)4 * 15! * (4*x2)6) / (4! * 12!) +
((-1)5 * 14! * (4*x2)5) / (5! * 10!) +
((-1)6 * 13! * (4*x2)4) / (6! * 8!) +
((-1)7 * 12! * (4*x2)3) / (7! * 6!) +
((-1)8 * 11! * (4*x2)2) / (8! * 4!) +
((-1)9 * 10! * (4*x2)1) / (9! * 2!) +
((-1)10 * 9! * (4*x2)0) / (10! * 0!)
?

Тогда ты будешь смеяться, но тебе вообще не нужна НИ функция вычисления факториала, НИ функция возведения в степень... Все, что нужно знать - это чему равен первый член ряда, и как изменяется относительно предыдущего последующий... Вот так будет выглядеть твоя функция:

function f(x: real): real;
var
  s, item: real;
  p, k: integer;
begin
  item := 1/10; s := item;
  for k := 9 downto 0 do begin

    if k = 9 then p := 1 else p := k + 1;
    item := - item * ((19 - k) * p * 4 * sqr(x)) /
                     (pred(2 * (10 - k)) * (2 * (10 - k)));
    s := s + item;
  end;
  f := 10 * s;
end;



Цитата
которая при х=1 равна 1'200'000 с хвостиком
Это ты преувеличила, при X = 1 значение функции равно 1, но вот растет оно очень быстро - уже F(1.1) становится равным 357.15, а уж при Х = 2 вообще 13 737 919 114.6, то есть больше 13 миллиардов...
зайка
не преувеличила либо ты не правильно посчитал либо не правильно задал у=1 при х=0, а при х=1 у=8654053

кстати у тебя почему то у тебя при х=0 у=8654053?

ты мне лучше скажи как мне функцию с процедурами правильно записать чтобы не переполнять?
у меня просто этих функций мама не горюй и если я у каждой буду члены вычислять меня в дурку заберутsmile.gif
volvo
Цитата
либо ты не правильно посчитал либо не правильно задал у=1 при х=0, а при х=1 у=8654053

А с чего ты вообще решила, что твое значение верно? Пересчитывай свое значение F(1)... Вот тебе второй вариант решения (практически дословно по формуле, ошибиться вообще негде):

function f(x: real): real;

  function pow(a: real; n: integer): real;
  var i: integer; p: real;
  begin
    p := 1;
    for i := 1 to n do p := p * a;
    pow := p;
  end;

var
  s, power: real;
  i, k: integer;
begin
  s := pow(4 * sqr(x), 10) / 20;
  for k := 1 to 10 do begin
    power := pow(4 * sqr(x), 10 - k);
    if odd(k) then power := - power;
    for i := 1 to pred(k) do begin
      power := power * (20 - k - i) / (i + 1);
    end;
    s := s + power;
  end;
  f := 10 * s;
end;

Чему будет равно значение F(0)? Единице... А F(1)? Упс, тоже единица... Так что учи матчасть dry.gif

Добавлено через 3 мин.
Цитата
кстати у тебя почему то у тебя при х=0 у=8654053?
Тебе по-моему уже хватит заниматься программированием:

Вот что мне выдается при
  x := 0;
  writeln(f(x) :10 :5); { <--- Старая функция F }


Цитата(Console)
Running "g:\programs\pascal\__test.exe"
1.00000
. Где ты видишь то ужасное значение, которое написано выше? Я его не наблюдаю...
зайка
ну ты понимаешь что здесь где-то ошибка ypriamii.gif
, т.к.
1. я в ручную задавала эту функцию(без процедур степеней и факториалов) и значения были совершенно другие;
2. я некот значения вручную просчитывала crazy.gif
3. у этой ф-и 4 симметричных корня +-0,446(приблизит) и +-1.68(тоже приблизит) blink.gif
зайка
немного не так надо ещё 20-2k+i
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.