Wykres funkcji

0

Witam
Mam do zrobienia program w Pascalu, który narysuje wykres funkcji dla podanego zakresu argumentów.
Napisałem coś takiego:

 program
 prostokat;
uses
 graph,crt;
var
 gd,gm:integer;
 x_max, x_min, y_max, y_min, licznik, roznica, przelicznik, roznica_x, roznica_y:real;
procedure uklad_wspolrzednych;
 begin
 MoveTo(GetMaxX div 2, GetMaxY div 2);
 LineRel(GetMaxX div 2-40,0);
 LineRel(-5, 5);
 MoveRel(5, -5);
 LineRel(-5, -5);
 MoveRel(5, 5);
 LineRel(-(GetMaxX div 2-40)*2,0);
 MoveTo(GetMaxX div 2, GetMaxY div 2);
 LineRel(0, GetMaxY div 2-20);
 LineRel(0,-(GetMaxY div 2-20)*2);
 LineRel(-5, 5);
 MoveRel(5, -5);
 LineRel(5, 5);
 end;
function funkcja(x:real):real;
 begin
 funkcja:=sin(x);
 end;
begin
 clrscr;
 writeln('Podaj definicje funkcji');
 write('Argument najmniejszy='); readln(x_min);
 write('Argument najwiekszy='); readln(x_max);
 y_min:=funkcja(x_min);
 licznik:=x_min;
 while licznik<x_max do begin
  if funkcja(licznik) < y_min then y_min:=funkcja(licznik);
  licznik:=licznik+0.01;
 end;
 y_max:=funkcja(x_min);
 licznik:=x_min;
 while licznik<x_max do begin
  if funkcja(licznik) > y_max then y_max:=funkcja(licznik);
  licznik:=licznik+0.01;
 end;

 roznica_y:=y_max-y_min;
 if (x_max>0) and (x_min>0) then roznica_x:=x_max else
   if (x_max<0) and (x_min<0) then roznica_x:=abs(x_min) else
     roznica_x:=(x_max-x_min);
 if roznica_x>roznica_y then roznica:=roznica_x else roznica:=roznica_y;

 DetectGraph(gd,gm);
 InitGraph(gd,gm, 'c:\progra~1\tp\bgi');
 przelicznik:=(GetMaxX-40)/2/roznica;
 uklad_wspolrzednych;
 licznik:=x_min;
 MoveTo((GetMaxX div 2)+round(przelicznik), (GetMaxY div 2));
 LineRel(0,15); LineRel(0,-30); SetTextStyle(3, 0, 2); MoveRel(-5,-30); OutText('1');
 while licznik<x_max do begin
  PutPixel((GetMaxX div 2)+round(licznik*przelicznik),(GetMaxY div 2)-round(funkcja(licznik)*przelicznik), green);
  licznik:=licznik+0.0001;
 end;
 repeat until KeyPressed;
 CloseGraph;
end.

Program niby działa, ale wymaga jeszcze kilku poprawek

  1. Co zrobić, aby wzór funkcji do narywowania wykresu wpisywać po uruchomieniu programu. Chodzi mi o coś takiego, że program wyświetli:
    "Podaj wzór funkcji
    f(x)="
    i będzie tu można wpisać np. "sin(x)", "2x", "xx" itd.
  2. Program obecnie nie rysuje wykresów dla funkcji 1/x, 2/x, 3/x itd. w przedziale od wartości ujemnej do dodatniej. Wpisanie do funkcji "if x=0 then funkcja(x):=0" nic nie daje. Jak można naprawić ten błąd?

Pozdrawiam

0
  1. np. zaimplementować ONP (więcej w serwisie/google/whatever)
  2. nie bardzo rozumiem - przecież dzielenie przez zero to błąd. Może z funkcji funkcja zwracaj NaN kiedy wartość jest niepoprawna a przy rysowaniu sprawdzaj czy funkcja(licznik) zwróciła NaN i wtedy nie rysuj tego pixela. Tylko nie pamiętam czy w pascalu była obsługa NaN
0

Dzięki za odpowiedź :)

  1. A czy istnieje jakiś prostszy sposób. Czytałem o odwrotnej notacji polskiej i jeśli wzór skladałby się tylko z liczb i operatorów + - * / to jeszcze nie byłoby tak źle, ale gdy wzór miałby np. taką postać f(x)=sin(abs(x))*cos(abs(x)) to już jest troszke gorzej :)
  2. Z tego co znalazłem to Pascal nie obsługuje NAN, ale jeśli w funkcji funkcja wstawiłem instrukcję if x=0 then funkcja:=0 else funkcja:=2/x; (czyli jeśli argumentem funkcji byłaby liczba 0 to funkcja powinna mieć wartość 0 i piksel powinien być postawiony w punkcie 0,0 układu wspólrzędnych, a dla wartości różnych od zera wartością funkcji powinno być 2/x) to i tak wykres funkcji w ogóle nie był rysowany.
0
  1. przy ONP nie ma różnicy czy będziesz miał tylko + i - czy do tego f. trygonometryczne, potęgowanie, pierwiastkowanie i co Ci tam przyjdzie do głowy - obliczenie wyrażenia w ONP jest banalne w stosunku do obliczenia chociażby 1+2*3.
  2. daj cały kod razem z tym if x = 0 ... bo naprawdę ciężko mi uwierzyć, aby ten if był przyczyną nierysowania funkcji
0

Jeśli dobrze zrozumiałem to z ONP mialoby to tak wyglądać: wzór funkcji pobrany jest jako string, następnia pętla sprawdza czy dany znak z tego stringa jest cyfrą czy innym znakiem, jeżeli jest cyfrą to zapisauje go do tablicy typu liczbowego (np. integer) a jeżeli jest znakiem to do tablicy typu char. Ale co jeśli petla napotka funkcję (np. sin())?

A tu jest kod z tą funkcją 2/x:

program
 prostokat;
uses
 graph,crt;
var
 gd,gm:integer;
 x_max, x_min, y_max, y_min, licznik, roznica, przelicznik, roznica_x, roznica_y:real;
procedure uklad_wspolrzednych;
 begin
 MoveTo(GetMaxX div 2, GetMaxY div 2);
 LineRel(GetMaxX div 2-40,0);
 LineRel(-5, 5);
 MoveRel(5, -5);
 LineRel(-5, -5);
 MoveRel(5, 5);
 LineRel(-(GetMaxX div 2-40)*2,0);
 MoveTo(GetMaxX div 2, GetMaxY div 2);
 LineRel(0, GetMaxY div 2-20);
 LineRel(0,-(GetMaxY div 2-20)*2);
 LineRel(-5, 5);
 MoveRel(5, -5);
 LineRel(5, 5);
 end;
function funkcja(x:real):real;
 begin
 if x=0 then funkcja:=0 else funkcja:=2/x;
 end;
begin
 clrscr;
 writeln('Podaj definicje funkcji');
 write('Argument najmniejszy='); readln(x_min);
 write('Argument najwiekszy='); readln(x_max);
 y_min:=funkcja(x_min);
 licznik:=x_min;
 while licznik<x_max do begin
  if funkcja(licznik) < y_min then y_min:=funkcja(licznik);
  licznik:=licznik+0.01;
 end;
 y_max:=funkcja(x_min);
 licznik:=x_min;
 while licznik<x_max do begin
  if funkcja(licznik) > y_max then y_max:=funkcja(licznik);
  licznik:=licznik+0.01;
 end;

 roznica_y:=y_max-y_min;
 if (x_max>0) and (x_min>0) then roznica_x:=x_max else
   if (x_max<0) and (x_min<0) then roznica_x:=abs(x_min) else
     roznica_x:=(x_max-x_min);
 if roznica_x>roznica_y then roznica:=roznica_x else roznica:=roznica_y;

 DetectGraph(gd,gm);
 InitGraph(gd,gm, 'c:\progra~1\tp\bgi');
 przelicznik:=(GetMaxX-40)/2/roznica;
 uklad_wspolrzednych;
 licznik:=x_min;
 MoveTo((GetMaxX div 2)+round(przelicznik), (GetMaxY div 2));
 LineRel(0,15); LineRel(0,-30); SetTextStyle(3, 0, 2); MoveRel(-5,-30); OutText('1');
 while licznik<x_max do begin
  PutPixel((GetMaxX div 2)+round(licznik*przelicznik),(GetMaxY div 2)-round(funkcja(licznik)*przelicznik), green);
  licznik:=licznik+0.0001;
 end;
 repeat until KeyPressed;
 CloseGraph;
end.
 
0

Zrezygnuje z tego wpisywania wzoru, ale co zrobić żeby program rysował wykres dla funkcji np. 2/x - gdy jest w funkcji instrukcja "if x=0 then funkcja:=0 else funkcja:=2/x;" to nie ma dzielenia przez zero (bo dla argumentu 0 powinna być wartość 0) i powinno rysować ten wykres.

1 użytkowników online, w tym zalogowanych: 0, gości: 1