Witam, dostałem na zadanie zrobienie kalkulatora liczb zespolonych w Lazarusie, jeśli mam być szczery do nie do końca wiem jak to powinno wyglądać, zrobiłem coś takiego(załącznik z projektem) i jest źle, błędnie oblicza fazę. Był bym wdzięczny za pomoc.
No to od czego by tu zacząć ... może od początku. Nie wiem czy zdajesz sobie sprawę ale operacje na liczbach zespolonych wykonuje się mniej więcej tak jak na wielomianach więc ten kod:
try
z1r:=StrToFloat(Edit1.Text);
z1i:=StrToFloat(Edit2.Text);
z2r:=StrToFloat(Edit3.Text);
z2i:=StrToFloat(Edit4.Text);
except
ShowMessage('Uzupelnij wszystkie pola cyframi');
end;
if Mnozenie.Checked then begin
wr:=z1r*z2r;
wi:=z1i*z2i;
end
else if Dzielenie.Checked then begin
wr:=z1r/z2r;
wi:=z1i/z2i;
end;
mniej więcej pokazuje, że jednak powinieneś najpierw nieco doczytać na temat tych liczb. Polecam:
http://obliczone.pl/wzory-i-w%C5%82asno%C5%9Bci/636-liczby-zespolone
Gdy zrozumiesz o co dokładnie chodzi to zakodowanie tego nie powinno być problemem.
Prosty przykład to przetestowania: (1 + i) * (3 + i) powinno dać Ci 2 + 4i pamiętaj bowiem że i^2=-1
Natomiast dzielenie (3+i) / (2+i) powinno dać Ci 7/5 - 1/5i
Ok do biorę się do przerabiania, choć wydaję mi się że wygodniej będzie pierwsze zamienić liczbę na postać wykładniczą i wtedy ją przemnożyć a następnie wrócić do postaci algebraicznej, tym bardziej że wynik zapisany w postaci wykładniczej też powinien być.
Problem z liczeniem wartości chyba rozwiązany, pozostaje problem z obliczaniem właściwego kąta, nie mam pojęcia dlaczego wypisuje zły kąt kiedy wartość Re z liczby jest równa zero. Mógł by ktoś rzucić okiem co może być nie tak.
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Edit5: TEdit;
Edit6: TEdit;
Edit7: TEdit;
Edit8: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Dodawanie: TRadioButton;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
Odejmowanie: TRadioButton;
Mnozenie: TRadioButton;
Dzielenie: TRadioButton;
Dzialania: TRadioGroup;
Stopnie: TRadioButton;
Radiany: TRadioButton;
Jednostka: TRadioGroup;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Edit1Change(Sender: TObject);
procedure Edit2Change(Sender: TObject);
procedure Edit3Change(Sender: TObject);
procedure Edit4Change(Sender: TObject);
procedure Edit5Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Label1Click(Sender: TObject);
procedure Label2Click(Sender: TObject);
procedure Label4Click(Sender: TObject);
procedure DodawanieChange(Sender: TObject);
procedure DzialaniaClick(Sender: TObject);
procedure MnozenieChange(Sender: TObject);
procedure OdejmowanieChange(Sender: TObject);
procedure JednostkaClick(Sender: TObject);
procedure RadianyChange(Sender: TObject);
procedure StopnieChange(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
var
z1r,z1i,z2r,z2i,wr,wi,wartosc,wykladnik,modul2,modul1,wyk1,wyk2:double;
implementation
{$R *.lfm}
{ TForm1 }
// Funkcja obliczająca faze;
function Faza(im:double; re:double): double;
begin
if re = 0 then begin
result:=PI/2;
end else begin
Result:= arctan(im/re);
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
end;
procedure TForm1.Edit1Change(Sender: TObject);
begin
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
z1r:=StrToFloat(Edit1.Text);
z1i:=StrToFloat(Edit2.Text);
z2r:=StrToFloat(Edit3.Text);
z2i:=StrToFloat(Edit4.Text);
//Dodawanie i odejmowanie
if Dodawanie.Checked then begin
wr:=z1r+z2r;
wi:=z1i+z2i;
//Obliczanie modulu dla wyniku dodawania oraz fazy
wartosc:= sqrt(wr*wr+wi*wi);
wykladnik:=(Faza(wi,wr)/PI)*180;
end
else if Odejmowanie.Checked then begin
wr:=z1r-z2r;
wi:=z1i-z2i;
//Obliczanie modulu dla wyniku odejmowania oraz fazy
wartosc:= sqrt(wr*wr+wi*wi);
wykladnik:=(Faza(wi,wr)/PI)*180;
end
else if Mnozenie.Checked then begin
//Obliczanie modulow
modul1:=sqrt(z1r*z1r+z1i*z1i);
modul2:=sqrt(z2r*z2r+z2i*z2i);
//Obliczanie fazy
wyk1:=Faza(z1i,z1r);
wyk2:=Faza(z2i,z2r);
ShowMessage(floattostr(wyk1));
ShowMessage(floattostr(wyk2));
//Wykonanie dzialania
wartosc:= modul1*modul2;
wykladnik:=((wyk1+wyk2)/PI)*180 ;
wr:=wartosc*(cos(wyk1+wyk2));
wi:=wartosc*(sin(wyk1+wyk2));
end
else if Dzielenie.Checked then begin
//Obliczanie modulow
modul1:=sqrt(z1r*z1r+z1i*z1i);
modul2:=sqrt(z2r*z2r+z2i*z2i);
//Obliczanie fazy
wyk1:=Faza(z1i,z1r);
wyk2:=Faza(z2i,z2r);
//Wykonanie dzialania
wartosc:= modul1/modul2;
wykladnik:=((wyk1-wyk2)/PI)*180 ;
wr:=wartosc*(cos(wyk1-wyk2));
wi:=wartosc*(sin(wyk1-wyk2));
end;
Edit5.Text:=FloatToStr(wr);
Edit6.Text:=FloatToStr(wi);
Edit7.Text:=FloatToStr(wartosc);
Edit8.Text:=FloatToStr(wykladnik);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Edit1.Text:=FloatToStr(0);
Edit2.Text:=FloatToStr(0);
Edit3.Text:=FloatToStr(0);
Edit4.Text:=FloatToStr(0);
Edit5.Text:=FloatToStr(0);
Edit6.Text:=FloatToStr(0);
Edit7.Text:=FloatToStr(0);
Edit8.Text:=FloatToStr(0);
end;
procedure TForm1.Edit2Change(Sender: TObject);
begin
end;
procedure TForm1.Edit3Change(Sender: TObject);
begin
end;
procedure TForm1.Edit4Change(Sender: TObject);
begin
end;
procedure TForm1.Edit5Change(Sender: TObject);
begin
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
end;
procedure TForm1.Label2Click(Sender: TObject);
begin
end;
procedure TForm1.Label4Click(Sender: TObject);
begin
end;
procedure TForm1.DodawanieChange(Sender: TObject);
begin
end;
procedure TForm1.DzialaniaClick(Sender: TObject);
begin
end;
procedure TForm1.MnozenieChange(Sender: TObject);
begin
end;
procedure TForm1.OdejmowanieChange(Sender: TObject);
begin
end;
procedure TForm1.JednostkaClick(Sender: TObject);
begin
end;
procedure TForm1.RadianyChange(Sender: TObject);
begin
end;
procedure TForm1.StopnieChange(Sender: TObject);
begin
end;
end.
faza nie jest pi/2 dla urojonych.
np. dla -1i faza będzie raptem 3/2 pi == -pi/2;
rozumiesz?