MATLAB mengenal dua keluarga operator aritmetika yang tidak saling menggantikan: operator matriks yang tunduk pada aturan aljabar linear, dan operator per elemen yang mengerjakan operasi pada pasangan elemen yang seposisi. Topik ini membahas perbedaan kedua keluarga tersebut, syarat dimensi yang berlaku bagi masing-masing, serta perilaku pembagian, perpangkatan, dan transpos pada tiap keluarga. Kedua keluarga kemudian dipakai bersama untuk menuliskan rumus polinomial pada seluruh vektor sekaligus. Penguasaan perbedaan ini menjadi modal utama teknik vektorisasi, yakni penyusunan perhitungan array tanpa perulangan eksplisit. Penguasaan yang sama juga menjadikan pesan error dimensi sebagai petunjuk keluarga operator mana yang seharusnya dipakai.
Dua keluarga operator aritmetika#
Operator aritmetika MATLAB terbagi menjadi dua keluarga dengan makna yang berbeda. Keluarga pertama adalah operator matriks, yaitu *, /, \, ^, dan ', yang menjalankan operasi aljabar linear seperti perkalian matriks, penyelesaian sistem linear, dan transpos. Keluarga kedua adalah operator per elemen (element-wise), ditandai sebuah titik sebelum simbolnya: .*, ./, .\, .^, dan .'. Operator per elemen mengerjakan operasi pada setiap pasangan elemen yang menempati posisi sama pada kedua operan.
Penjumlahan dan pengurangan tidak memiliki bentuk bertitik karena penjumlahan matriks memang dikerjakan elemen demi elemen, sehingga + dan - langsung menjadi anggota keluarga per elemen. Tabel berikut merangkum kedua keluarga operator berikut pasangannya.
| Operasi | Keluarga matriks | Keluarga per elemen |
|---|---|---|
| Perkalian | * | .* |
| Pembagian kanan | / | ./ |
| Pembagian kiri | \ | .\ |
| Perpangkatan | ^ | .^ |
| Transpos | ' | .' |
Keberadaan dua keluarga berakar pada asal MATLAB sebagai laboratorium matriks. Perkalian dua matriks memiliki makna baku di aljabar linear, dan makna itu berbeda dari perkalian dua bilangan. Ketika maksud perhitungan adalah rumus yang berlaku pada tiap elemen data, operator bertitik yang dipilih. Ketika maksudnya relasi antar dimensi seperti hasil kali dalam atau penyelesaian sistem, operator tanpa titik yang dipilih.
Perkalian matriks dan perkalian per elemen#
Perkalian matriks * mensyaratkan banyak kolom operan pertama sama dengan banyak baris operan kedua, sesuai aturan baris demi kolom pada aljabar linear. Perkalian per elemen .* mensyaratkan kedua operan berukuran sama, atau salah satunya skalar yang kemudian tersebar ke seluruh elemen. Syarat yang berbeda ini membuat pemilihan operator yang salah langsung terlihat ketika kode dijalankan.
u = [1 2 3];
v = [4 5 6];
u .* v
try
u * v
catch e
disp(e.message)
end
u * v'ans =
4 10 18
operator *: nonconformant arguments (op1 is 1x3, op2 is 1x3)
ans = 32Perkalian u .* v memasangkan 1 dengan 4, 2 dengan 5, dan 3 dengan 6, sehingga hasilnya vektor [4 10 18]. Perkalian u * v ditolak karena banyak kolom u, yaitu tiga, tidak sama dengan banyak baris v, yaitu satu, dan pesan errornya melaporkan ukuran kedua operan. Sebaliknya, u * v' sah karena v' berukuran , dan hasil 32 adalah hasil kali dalam (inner product) kedua vektor, yakni . Kontras ketiganya menegaskan pembagian tugas antara kedua keluarga operator: * melayani relasi antar dimensi, sedangkan .* melayani rumus pada data.
Pembagian dan perpangkatan per elemen#
Aturan yang sama berlaku pada pembagian dan perpangkatan. Operator ./ membagi setiap pasangan elemen seposisi, sedangkan / melakukan pembagian matriks yang penyelesaiannya dibahas pada modul aljabar linear. Operator .^ memangkatkan setiap elemen, sedangkan ^ hanya menerima perpangkatan matriks persegi atau kombinasi dengan skalar. Perbedaan ini muncul begitu kedua operan berupa array.
x = [2 4 8];
x .^ 2
x ./ [2 1 4]
try
x ^ 2
catch e
disp(e.message)
endans =
4 16 64
ans =
1 4 2
for x^y, only square matrix arguments are permitted and one argument must be scalar. Use .^ for elementwise power.Pernyataan x .^ 2 menghasilkan [4 16 64] karena setiap elemen dipangkatkan dua, dan x ./ [2 1 4] membagi elemen x dengan pasangannya sehingga menghasilkan [1 4 2]. Bentuk x ^ 2 ditolak karena x bukan matriks persegi, dan pesan penolakan pada Octave bahkan menyebut .^ sebagai bentuk yang dimaksud. Ketika salah satu operan berupa skalar, kedua keluarga bertemu: x / 2 dan x ./ 2 sama-sama membagi setiap elemen karena penyebaran skalar berlaku pada keduanya. Jalan pintas ini aman selama operan skalar tetap skalar, dan jebakannya dibahas pada bagian Kesalahan umum.
Transpos biasa dan transpos konjugat#
Operator transpose juga terbagi dua. Tanda petik ' menjalankan transpos konjugat (complex conjugate transpose), yang membalik dimensi dan sekaligus mengganti tanda bagian imajiner setiap elemen kompleks. Tanda petik didahului titik, yaitu .', menjalankan transpos biasa yang hanya membalik dimensi tanpa mengubah nilai elemennya. Pada data riil keduanya menghasilkan hal yang sama, sehingga kekeliruan pemilihan tidak terlihat sampai data kompleks masuk ke dalam perhitungan.
z = [1+2i 3-1i];
z'
z.'ans =
1 - 2i
3 + 1i
ans =
1 + 2i
3 - 1iHasil z' berisi 1 - 2i dan 3 + 1i karena bagian imajiner tiap elemen dibalik tandanya, sedangkan z.' mempertahankan nilai aslinya dan hanya mengubah arah menjadi vektor kolom. Pada pengolahan sinyal dan perhitungan domain frekuensi, konjugasi mengubah hasil secara substantif, misalnya pada besar energi sebuah spektrum kompleks. Karena itu kebiasaan yang aman adalah menuliskan .' ketika maksudnya benar-benar sekadar menukar orientasi, dan memakai ' hanya ketika konjugasi memang bagian dari rumus.
Polinomial pada seluruh vektor sekaligus#
Manfaat terbesar operator per elemen adalah penulisan rumus pada seluruh data dalam satu pernyataan. Rumus polinomial dievaluasi pada banyak titik sekaligus dengan mencampur kedua keluarga operator. Suku cukup memakai * karena koefisien skalar tersebar ke seluruh elemen x, sedangkan suku wajib memakai .^ karena pangkat dikerjakan pada tiap elemen. Skrip berikut membandingkan bentuk tervektorisasi dengan padanan perulangannya.
% polinomial.m: mengevaluasi polinomial pada banyak titik sekaligus
a0 = 1;
a1 = -2;
a2 = 1;
x = 0:5;
% bentuk tervektorisasi: satu pernyataan untuk seluruh titik
y = a0 + a1*x + a2*x.^2;
% padanan perulangan yang digantikan oleh pernyataan di atas
y_perulangan = zeros(size(x));
for k = 1:numel(x)
y_perulangan(k) = a0 + a1*x(k) + a2*x(k)^2;
end
fprintf('titik x:\n');
disp(x);
fprintf('nilai y (tervektorisasi):\n');
disp(y);
fprintf('selisih maksimum terhadap versi perulangan: %g\n', max(abs(y - y_perulangan)));titik x:
0 1 2 3 4 5
nilai y (tervektorisasi):
1 0 1 4 9 16
selisih maksimum terhadap versi perulangan: 0Koefisien 1, -2, dan 1 membentuk polinomial , sehingga titik 0 sampai 5 menghasilkan nilai [1 0 1 4 9 16]. Versi perulangan menghitung nilai yang sama dengan menjelajah titik satu per satu, dan selisih maksimum nol membuktikan keduanya setara. Perbedaannya bukan pada hasil, melainkan pada bentuk: satu pernyataan mengikuti rumus tertulisnya, sementara perulangan menambah dua baris penyangga berupa pencacah dan penugasan per elemen. Pola inilah yang dikembangkan menjadi prosedur refaktor lengkap pada topik refaktor perulangan ke vektor.
Kesalahan umum#
- Menyimpulkan bahwa
/bekerja per elemen karena1/2 * xberjalan. Perkalian dan pembagian dikerjakan dari kiri ke kanan, sehingga1/2 * xmembentuk skalar 0.5 lebih dahulu dan skalar tersebut tersebar ke seluruh elemen. Kesimpulan itu runtuh begitu pembilangnya berupa array, sebagaimana contoh berikut.
x = [2 4 8];
1/2 * x
try
2 / x
catch e
disp(e.message)
end
1 ./ xans =
1 2 4
operator /: nonconformant arguments (op1 is 1x1, op2 is 1x3)
ans =
0.5000 0.2500 0.1250- Memakai pangkat matriks tanpa sengaja pada matriks persegi. Pada matriks persegi,
^dan.^sama-sama berjalan tanpa error tetapi menghasilkan hal yang berbeda: yang pertama mengalikan matriks dengan dirinya menurut aturan aljabar linear, yang kedua memangkatkan tiap elemen. Kekeliruan ini lolos secara diam-diam, sehingga maksud operasi perlu dipastikan sebelum memilih operator.
A = [1 2; 3 4];
A ^ 2
A .^ 2ans =
7 10
15 22
ans =
1 4
9 16- Menukar
'dan.'pada data kompleks. Kedua operator sama-sama sah dan hasilnya berbeda tanpa peringatan apa pun. Gunakan.'untuk sekadar menukar orientasi, dan'hanya ketika konjugasi memang bagian dari rumus yang ditulis.
Ringkasan#
- Operator matriks menjalankan aturan aljabar linear dengan syarat dimensi dalam yang cocok, sedangkan operator bertitik mengerjakan operasi pada pasangan elemen seposisi dengan syarat ukuran yang sama atau skalar.
- Operator
/,^, dan'tidak menjadi operasi per elemen hanya karena salah satu operan kebetulan skalar atau data kebetulan riil. - Rumus polinomial pada vektor ditulis dengan mencampur kedua keluarga: suku dengan operan skalar cukup memakai operator biasa, sedangkan suku yang melibatkan dua array memakai operator bertitik.
- Kekeliruan keluarga operator pada matriks persegi tidak memicu error, sehingga hasil yang salah hanya dapat dicegah dengan memastikan maksud operasi sebelum menulis operatornya.
Referensi#
- Array vs. Matrix Operations — MathWorks — Panduan resmi perbedaan operasi array dan operasi matriks beserta tabel operatornya.
- times, .* — MathWorks — Rujukan operator perkalian per elemen lengkap dengan syarat ukurannya.
- power, .^ — MathWorks — Rujukan operator perpangkatan per elemen pada array.
- ctranspose, ’ — MathWorks — Rujukan transpos konjugat kompleks.
- transpose, .’ — MathWorks — Rujukan transpos tanpa konjugasi.