Klasa szablonowa complex
służy do reprezentacji i manipulacji liczbami zespolonymi. Operacje zdefiniowane na liczbach zespolonych pozwalają na swobodne mieszanie obiektów tej klasy z wbudowanymi typami numerycznymi. Należy zauważyć, że większość operacji wykonywanych na obiektach tej klasy to zwykłe funkcje. Wyjątkami są metody real()
i imag()
należące do klasy complex
.
Argument szablonu określa typ związany z wartościami części rzeczywistej i urojonej obiektu. Ten argument musi być jednym z trzech dostępnych typów zmiennoprzecinkowych float
, double
lub long double
.
Dostępne są cztery konstruktory. Konstruktor bezparametrowy inicjalizuje obie części liczby zespolonej wartością zero. Konstruktor jednoargumentowy incjalizuje wartością parametru część rzeczywistą i zeruje urojoną. Konstruktor dwuargumentowy inicjalizuje obie części liczby zespolonej. Ostatecznie, konstruktor kopiujący pozwala inicjalizować obiekt wartościami innego dostępnego obiektu klasy.
complex<double> cplx_one; // wartość 0 + 0i complex<double> cplx_two(3.14); // wartość 3.14 + 0i complex<double> cplx_three(1.5, 3.14) // wartość 1.5 + 3.14i complex<double> cplx_four(cplx_two); // wartość również 3.14 + 0i
Liczbie zespolonej complex
można przypisać wartość innej liczby zespolonej. Ponieważ konstruktor jednoargumentowy jest również wykorzystywany jako operator konwersji, można przypisać liczbie zespolonej wartość rzeczywistą.
cplx_one = cplx_three; // staje się 1.5 + 3.14i cplx_three = 2.17; // staje się 2.17 + 0i
Funkcja polar()
może służyć do konstrukcji liczby zespolonej dla danego modułu i fazy kąta.
cplx_four = polar(5.6, 1.8);
Wartość sprzężona powstaje z użyciem funkcji conj()
.
complex<double> cplx_five = conj(cplx_four);
Metody klasy complex
real()
i imag()
zwracają wartości odpowiednio części rzeczywistej i urojonej liczby zespolonej. Funkcje te można również wywołać jako zwykłe funkcje z obiektem klasy complex
jako argument.
cout << cplx_one.real() << "+" << cplx_one.imag() << "i" << endl; cout << real(cplx_one) << "+" << imag(cplx_one) << "i" << endl;
Operatory artmetyczne +
, -
, *
oraz /
mogą być używane zgodnie z przyjętą konwencją. Wszystkie przyjmują jako argumenty albo dwie liczby zespolone albo liczbę zespoloną i wartość rzeczywistą. Ponadto zdefiniowane są dla każdego z nich operatory przypisania.
cout << cplx_one + cplx_two << endl; // wartość 4.64+3.14i cout << cplx_one - 3.14 << endl; // wartość -1.64+3.14i cout << 2.75 * cplx_two << endl; // wartość 8.635+0i cout << (cplx_one += cplx_three / 2.0) << endl; // wartość 2.585+3.14i
Operatory jednoargumentowe +
i -
również można używać.
cout << -cplx_one << endl; // wartość -2.585-3.14i
Dwie liczby zespolone complex
mogą być przetestowane na równość lub nierówność wykorzystując operatory ==
i !=
. Dwie wartości są równe, gdy odpowiadające sobie części rzeczywiste i urojone liczb są sobie równe.
cout << (cplx_one == cplx_three) << endl; // wartość 0 (fałsz) cout << (cplx_one != cplx_three) << endl; // wartość 1 (prawda)
Liczby zespolone nie mogą być porównywane za pomocą innych operatorów, tzn. niedostępne są operatory porządkujące.
Liczby zespolone klasy complex
mogą być pisane do strumienia bądź z niego czytane wykorzystując przyjętą konwencję dla strumieni I/O. Wartość pisana jest do strumienia w nawiasach jako (u,v)
. Wartość jest czytana ze strumienia jako dwie wartości numeryczne oddzielone przecinkiem i otoczone nawiasami. Przykłady można znaleźć w kodzie na końcu strony.
Funkcja norm()
zwraca normę liczby zespolonej, która odpowiada sumie kwadratów części rzeczywistej i urojonej. Funkcja abs()
zwraca moduł, który jest pierwiastkiem kwadratowym normy liczby zespolonej.
cout << norm(cplx_two) << endl; cout << abs(cplx_two) << endl;
Kąt fazowy liczby zespolonej można uzyskać za pomocą funkcji arg()
.
cout << cplx_four << " w postaci biegunowej wynosi " << abs(cplx_four) << "e^" << arg(cplx_four) << "i"<< endl;
Funkcje trygonometryczne zdefiniowane dla typów zmiennoprzecinkowych zostały rozszerzone dla liczb zespolonych. Dotyczy to funkcji sin()
, cos()
, tan()
, sinh()
, cosh()
i tanh()
. Każda z nich bierze jako argument liczbę zespoloną complex i zwraca liczbę zespoloną.
Podobnie jak funkcje trygonometryczne funkcje exp()
, log()
, log10()
i sqrt()
zostały rozszerzone dla liczb zespolonych. Jako argument biorą obiekt complex
i zwracają również obiekt complex
.
Biblioteka standardowa definiuje kilka wersji funkcji pow()
. Istnieją osobne definicje dotyczące podnoszenia liczb zespolonych do wartości całkowitej, zespolonej i rzeczywistej. Podobnie można podnosić wartość rzeczywistą do wartości complex
.
W poniższym kodzie zebrano przykłady dostępne na tej stronie opisujące podstawowe funkcje klasu complex
. Ponadto dodano prostą funkcję obrazującą przykładowe zastosowanie klasy w celu obliczenia pierwiastków funkcji kwadratowej o współczynnikach zespolonych. Poniższy kod dostępny jest tutaj.
/* Autor: Łukasz Romanowski Biblioteka standardowa: <complex> Opis: Klasa szablonowa complex służy do reprezentacji i manipulacji liczbami zespolonymi. Operacje zdefiniowane na liczbach zespolonych pozwalają na swobodne mieszanie obiektów tej klasy z wbudowanymi typami numerycznymi. Należy zauważyć, że większość operacji wykonywanych na obiektach tej klasy to zwykłe funkcje. Wyjątkami są metody real() i imag() należące do klasy complex. */ #include <iostream> #include <complex> #include <utility> using namespace std; typedef complex<double> Complex; // deklaracja funkcji obliczajacej pierwiastki kwadratowe równania o współczynnikach zespolonych // implementacja poniżej pair<Complex, Complex> roots (Complex a, Complex b, Complex c); int main() { // deklaracje wykorzystujące rózne konstruktory dostępne w bibliotece standardowej complex<double> cplx_one; // wartość 0 + 0i complex<double> cplx_two(3.14); // wartość 3.14 + 0i complex<double> cplx_three(1.5, 3.14); // wartość 1.5 + 3.14i complex<double> cplx_four(cplx_two); // wartość również 3.14 + 0i cout << "cplx_one: " << cplx_one << endl; cout << "cplx_two: " << cplx_two << endl; cout << "cplx_three: " << cplx_three << endl; cout << "cplx_four: " << cplx_four << endl; // wykorzystanie operatora przypisania oraz konwersji za pomocą konstruktora jednoargumentowego cplx_one = cplx_three; // staje się 1.5 + 3.14i cplx_three = 2.17; // staje się 2.17 + 0i cout << "cplx_one: " << cplx_one << endl; cout << "cplx_three: " << cplx_three << endl; // wykorzystanie funkcji polar() do konstrukcji liczby zespolonej na podstawie modułu i kąta fazowego cplx_four = polar(5.6, 1.8); cout << "cplx_four: " << cplx_four << endl; // wartosc sprzężoną otrzymujemy za pomocą funkcji conj() complex<double> cplx_five = conj(cplx_four); cout << "cplx_five: " << cplx_five << endl; // aby otrzymać wartości części rzeczywistej i urojonej korzystamy z funkcji real() i imag() cout << cplx_one.real() << "+" << cplx_one.imag() << "i" << endl; cout << real(cplx_one) << "+" << imag(cplx_one) << "i" << endl; // operatory można wykorzystywać zgodnie z przyjętą konwencją cout << cplx_one + cplx_two << endl; // wartość (4.64,3.14) cout << cplx_one - 3.14 << endl; // wartość (-1.64,3.14) cout << 2.75 * cplx_two << endl; // wartość (8.635,0) cout << (cplx_one += cplx_three / 2.0) << endl; // wartość (2.585,3.14) // dostepne są również operatory jednoargumentowe + i - cout << -cplx_one << endl; // wartość (-2.585,-3.14) // do porównania wartości dwóch liczb zespolonych używamy operatorów == i !=, // pozostałe operatory porównujące są niedostępne cout << (cplx_one == cplx_three) << endl; // wartość 0 (fałsz) cout << (cplx_one != cplx_three) << endl; // wartość 1 (prawda) // wartości normalna i moduł dostępne są za pomocą funkcji norm() i abs() cout << norm(cplx_two) << endl; cout << abs(cplx_two) << endl; // kąt fazowy można uzyskać za pomocą funkcji funkcji arg() cout << cplx_four << " w postaci biegunowej wynosi " << abs(cplx_four) << "e^" << arg(cplx_four) << "i"<< endl; /* przykład wykorzystania klasy complex<> do obliczenia pierwiastków równania danego wzorem: (2,1)*x^2 + (0,1)*x + (5,0) = 0; W celu przetestowania działania funkcji należy zmieniać wartości a, b i c dane poniżej */ Complex a(2,1); Complex b(0,1); Complex c(5,0); pair<Complex,Complex> res(roots(a,b,c)); cout << "Wyniki przykładowej funkcji roots() obliczającej pierwiastki równania" << endl << a << "*x^2 + " << b << "*x + " << c << " = 0" << endl; cout << " x1= " << res.first << endl; cout << " x2= " << res.second << endl; } // definicja funkcji obliczajacej pierwiastki kwadratowe równania o współczynnikach zespolonych pair<Complex, Complex> roots (Complex a, Complex b, Complex c) { Complex root = sqrt(b * b - 4.0 * a * c); a *= 2.0; return make_pair( (-b + root)/a, (-b - root)/a ); }