Stworzenie wykresu ciągu Fibonacciego

0

Witam. To mój pierwszy post, także postaram się wyjaśnić w czym tkwi problem. Napisałem aplikację/program w Delphi 5, który pokazuje mi n-tą liczbę ciągu Fibonacciego. Potrzebuję zrobić wykres ciągu Fibonacciego (w załączniku), ale nie wiem jak się za to zabrać. Nic ciekawego do tej pory nie znalazłem, wiem o funkcji TChart i przycisku, pod którym znajdzie się funkcja generująca wykres, ale nie potrafię tego ruszyć. W załączniku dodałem również screen programu.

Kod

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, jpeg, ExtCtrls, TeeProcs, TeEngine, Chart;

type
  TForm1 = class(TForm)
    Edit2: TEdit;
    Button1: TButton;
    Label2: TLabel;
    Edit1: TEdit;
    Label3: TLabel;
    Image1: TImage;
    Button2: TButton;
    Chart1: TChart;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    function F(n: integer): integer;
    procedure Button2Click(Sender: TObject);
  private

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.F(n: integer): integer;
begin
if n=1 then
   begin
   F:=1;
   exit
   end;
if n=2 then
   begin
   F:=1;
   exit
   end;
F:=F(n-2)+F(n-1)
end;

procedure TForm1.Button1Click(Sender: TObject);
var n: integer;
begin
n:=strtoint(edit1.Text);
edit2.Text:=inttostr(F(n))
end;


procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;

end.
0

Do Delphi5 dołączone są przykłady korzystania z komponentu TChart

2

jeśli cały twój wkład w projekt na zaliczeni to aż 12 linii kodu (które do 5 można by skrócić) to pogratulować...

1
barney_ross napisał(a):


function TForm1.F(n: integer): integer;
begin
if n=1 then
   begin
   F:=1;
   exit
   end;
if n=2 then
   begin
   F:=1;
   exit
   end;
F:=F(n-2)+F(n-1)
end;

Odniosę się do tego.

  1. Liczysz rekurencyjnie a to wcale nie jest optymalne rozwiązanie. Liczyłeś np. 50 element? Sprawdź sobie ile czasu to zajmuje.

Sprawdź też to rozwiązanie:

function fib(n: integer): integer;
var
  i: integer;
  a, b: integer;
begin
  a := 0;
  b := 1;
  for i := 1 to n do
  begin
    b := b + a;
    a := b - a;
  end;
  result := a;
end;
  1. Przyjmujesz że ta funkcja jest jedną z metod klasy TForm. Zastanów się nad sensem takiego podejścia. Zgodnie z SOLID i SRP (zasada jednej odpowiedzialności), TForm (czyli formatka) nie powinna być odpowiedzialna za obliczanie Fibonacciego. Czy nie lepiej użyć jakiegoś odrębnego modułu a w nim ta funkcja?

Ale jak już napisałeś to powinno być tak:


function TForm1.GetFibonacciNumber(n: integer): integer;
begin
  if (n = 0) or (n = 1) then
  begin
   result := n;
  end;
  else
  begin
    result := GetFibonacciNumber(n - 2) + GetFibonacciNumber(n - 1);
  end;
end;

Testowałeś poprawność tej funkcji? Pamiętaj też o zasadach formatowania kodu Delphi i nazewnictwie.

0

Nie potrafię zrozumieć kretyńskiego programu nauczania na studiach. Dlaczego uczą tak debilnych i nieoptymalnych rozwiązań jak liczenie Fibonacciego rekurencyjnie czy sortowania bąbelkowego kiedy to są szybsze algorytmy, jednocześnie zaśmiecając tym głowę biednym studentom?

Mógłbym podać jeszcze wiele innych przykładów, jak np. obliczanie wyznacznika macierzy metodą rozwinięcia Laplace'a czy odwracanie macierzy tą metodą. Liczył ktoś w ten sposób wyznacznik macierzy 100x100? Ile to zajmuje?

2

Nie wiemy, kto wybrał sposób liczenia Fibonacciego - autor zadania czy autor wątku. Rekurencja (z zapamiętywaniem!) nie jest dla Fibonacciego zła:

  • nie trzeba mieć dodatkowej wiedzy o Fibonaccim, wystarczy definicja ciągu (która jest rekurencyjna),
  • na typach prostych da się wyliczyć Fibonacciego tylko dla tak małych liczb, że wydajność nie ma żadnego znaczenia. Pod warunkiem, że nie stosuje się zwykłej rekurencji, która prowadzi do obliczania wyrazów ciągu poprzez sumowanie jedynek (plus wielokrotne wywoływania funkcji), a taki np. f98 = 135 301 852 344 706 746 049.
0

A jeżeli chodzi o funkcję rysującą wykres, to ogarnąłem następujący kod, wydaje się trochę długi, nie wiem czy da nie lepiej byłoby zrobić to przy pomocy TChart.

procedure TForm1.Button3Click(Sender: TObject);
var i,j,k,l,tmp1,tmp2:integer;



begin
i:=0;
j:=0;
k:=0;
l:=0;
tmp1:=0;
tmp2:=0;
//osie x i y
Canvas.MoveTo(100, 400);
Canvas.LineTo(400, 400);
Canvas.MoveTo(100, 190);
Canvas.LineTo(100, 400);

// wypisanie na osi x wartosci
for k:=0 to 10 do
begin

Canvas.TextOut(100+i, 402, IntToStr(j));

i:=i+30;
j:=j+1;
end;
//opisanie osi x
Canvas.TextOut(420, 402, 'n');
i:=0;
j:=0;
//wypisanie wartosci na osi y
for k:=0 to 6 do
begin
Canvas.TextOut(85, 400-i, IntToStr(j));
i:=i+30;
j:=j+10;
end;
//opisanie osi y
Canvas.TextOut(85, 190, 'F(n)');

i:=0;
j:=0;
//przeliczenie wspolrzednych dla punktow
for l:=0 to 10 do
begin
if l=0 then
begin
Canvas.Brush.Color:=clRed;
Canvas.Ellipse(98, 398, 102, 402);
end;

if l=1  then
begin
Canvas.Ellipse(100+i-2, 400-j-2, 100+i+2, 400-j+2);
end ;

i:=i+30;
j:=j+5;
end;
// punkty od 2-10 inaczej nie moglem przeliczyc
Canvas.Ellipse(158, 393, 162, 397);
Canvas.Ellipse(188, 391, 192, 395);
Canvas.Ellipse(218, 389, 222, 393);
Canvas.Ellipse(248, 385, 252, 389);
Canvas.Ellipse(278, 381, 282, 385);
Canvas.Ellipse(308, 364, 312, 368);
Canvas.Ellipse(338, 344, 342, 348);
Canvas.Ellipse(368, 315, 372, 319);
Canvas.Ellipse(398, 245, 402, 249);
//podpisanie wykresu
Canvas.TextOut(110, 210, 'Wykres funkcji dla pierwszych dziesięciu wyrazów ciągu Fibonacciego');

end;



end 

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