Sampai babak ini semua angka kita berjalan di satu garis lurus; bilangan complex membukanya ke bidang dua dimensi dengan menyimpan sepasang nilai — bagian real dan bagian imajiner — dalam satu objek. Header <complex> menyediakan template std::complex<double> yang perilakunya dirancang seperti tipe angka biasa: operator +, -, *, / bekerja dengan aturan aljabar complex, sementara fungsi abs, arg, dan conj membaca sisi geometrisnya (panjang vektor, sudut, dan pencerminan terhadap sumbu real). Perkalian complex punya tafsir yang elegan: mengalikan dengan bilangan bermodulus 1 sama dengan memutar titik — cara paling ringkas melakukan rotasi dua dimensi tanpa fungsi trigonometri yang berhamburan. Kita buktikan semua itu dengan program teruji, termasuk artefak floating-point kecil yang persis seperti yang dibedah di Chapter Floating Point Precision.
std::complex: Dua Nilai, Satu Objek #
std::complex<double> pada dasarnya adalah pasangan double (bagian real dan imajiner) plus seperangkat operator yang menghitung dengan benar. Ada tiga cara lazim membuatnya: konstruktor std::complex<double> z(3.0, 4.0), assignment dari literal 3.0 + 4.0i setelah mengaktifkan using namespace std::complex_literals, atau lewat std::polar(modulus, sudut) untuk koordinat kutub. Pencetakan default stream memakai format (real,imag) — (3,4) untuk z kita — jadi jangan bingung saat output tampak seperti pasangan berkurung. Tipe ini bisa masuk std::vector, dijumlahkan dengan std::accumulate, dan dikirim ke fungsi seperti angka biasa; abstraksinya nyaris tanpa biaya karena compiler meletakkan kedua double berdampingan di memori.
Aritmetika dan Fungsi Geometris #
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
int main() {
using namespace std::complex_literals; // mengaktifkan literal i
// 1. Membuat dan membaca bilangan complex
std::complex<double> z = 3.0 + 4.0i;
std::cout << "z = " << z << "\n";
std::cout << "real = " << z.real() << "\n";
std::cout << "imag = " << z.imag() << "\n";
// 2. Aritmetika bekerja seperti tipe angka biasa
std::complex<double> w = 1.0 + 2.0i;
std::cout << "z + w = " << z + w << "\n";
std::cout << "z * w = " << z * w << "\n";
std::cout << "z / w = " << z / w << "\n";
// 3. Konjugat, modulus, dan argumen
std::cout << "conj(z) = " << std::conj(z) << "\n";
std::cout << "abs(z) = " << std::abs(z) << "\n";
std::cout << "arg(z) = " << std::arg(z) << "\n";
// 4. Rotasi 90 derajat: kalikan dengan bilangan satuan polar
std::complex<double> titik(1.0, 0.0); // titik (1, 0)
std::complex<double> rotasi = std::polar(1.0, std::acos(-1.0) / 2.0);
std::cout << "rotasi90 = " << titik * rotasi << "\n";
return 0;
}Output yang Dihasilkan:
z = (3,4)
real = 3
imag = 4
z + w = (4,6)
z * w = (-5,10)
z / w = (2.2,-0.4)
conj(z) = (3,-4)
abs(z) = 5
arg(z) = 0.927295
rotasi90 = (6.12323e-17,1)Bedah baris-per-baris:
- Baris 7 (
using namespace std::complex_literals;): mengaktifkan literal complexi(untukdouble),if(float), danil(long double) sehingga4.0ilangsung menjadistd::complex<double>dengan bagian real 0 — penulisan yang paling mendekati notasi matematika. - Baris 10-13 (
std::complex<double> z = 3.0 + 4.0i; ...): z menyimpan 3 sebagai real dan 4 sebagai imajiner. Aksesorz.real()danz.imag()membaca komponennya, dan stream mencetak seluruh objek sebagai(3,4). - Baris 17-19 (
z + w ... z * w ... z / w): penjumlahan menjumlahkan komponen per komponen →(4,6). Perkalian mengikuti aturan aljabar complex: (3+4i)(1+2i) = 3 + 6i + 4i + 8i² = -5 + 10i →(-5,10). Pembagian mengalikan dengan konjugat penyebut: (3+4i)/(1+2i) = (3+4i)(1-2i)/5 = (11-2i)/5 →(2.2,-0.4). Anda tidak menulis langkah-langkah itu — operator yang mengerjakan. - Baris 22 (
std::conj(z)): konjugat membalik tanda bagian imajiner →(3,-4), seperti pencerminan terhadap sumbu horizontal; berguna untuk pembagian manual dan sifatz * conj(z) = |z|². - Baris 23-24 (
std::abs(z) ... std::arg(z)):absadalah modulus — panjang vektor (3,4) yang terkenal 5 (teorema Pythagoras).argadalah sudut terhadap sumbu real dalam radian,atan2(4, 3)≈ 0,927295 (sekitar 53,13°). - Baris 27-28 (
titik(1.0, 0.0) ... std::polar(1.0, std::acos(-1.0) / 2.0)):std::polar(r, θ)membangun bilangan r·e^(iθ); dengan r = 1 dan θ = π/2 kita mendapat bilangan rotasi murni — modulusnya 1, argumennya 90°. - Baris 29 (
titik * rotasi): mengalikan titik (1,0) dengan bilangan rotasi memutarnya 90° → hasil yang diharapkan (0,1). Output menunjukkan(6.12323e-17,1)— bagian imajiner tepat 1, tetapi bagian real menyisakan 6,12 × 10⁻¹⁷, bukan 0 persis.
Membaca Artefak Rotasi #
Angka 6.12323e-17 pada baris terakhir bukan cacat program — itu cos(π/2) dalam double yang tidak bisa ditulis persis dalam biner, tema yang sudah kita bahas dua chapter berturut-turut. Implikasinya praktis: setelah banyak rotasi beruntun, sudut dan posisi akan menyerap galat kecil yang menumpuk (rotasi ulang 360° tidak persis kembali ke titik awal), jadi rutin geometri yang panjang sebaiknya memeriksa hasil dengan toleransi relatif seperti fungsi hampirSama pada Chapter Floating Point Precision. Sisi terangnya, std::complex menyimpan seluruh matematika rotasi dalam satu operator * — tanpa deretan cos, sin, dan tanda minus yang mudah tertukar.
Satu bilangan complex kini bisa dianggap sebagai vektor dua komponen yang matematikanya lengkap. Chapter berikutnya menggeneralisasi ide itu ke ukuran berapa pun — vektor n komponen dan matriks n×m — dan menimbang dua cara menyimpannya di C++: nested container atau satu larik datar.
Rujukan resmi untuk topik Chapter ini: std::complex dan pustaka numerik C++ di cppreference.