Bagian 1 memberi kita kerangka yang hidup, tetapi setiap operasi masih berupa pesan placeholder. Sekarang kita membangun mesin hitungnya. Setiap operasi menjadi fungsi kecil berdiri sendiri di src/ — antarmuka (menu, prompt, pencetakan) dan mesin (hitungan, validasi) dipisahkan agar fungsi-fungsi ini bisa diuji langsung tanpa menjalankan program utuh.
Yang kita bangun pada bagian ini:
- lima operasi:
tambahMatriks,kurangMatriks,kaliMatriks,transposeMatriks,determinanMatriks, - validasi dimensi dengan pesan galat yang menyebut kedua ukuran,
tampilkanMatriksuntuk mencetak hasil dengan kolom rata kanan,- uji unit pertama yang membuktikan tiap operasi benar.
Operasi Biner: Tambah dan Kurang #
Penjumlahan dan pengurangan matriks bekerja elemen demi elemen, sehingga kedua matriks wajib berukuran sama. Berikut seluruh isi src/tambahMatriks.m:
function C = tambahMatriks(A, B)
% TAMBAHMATRIKS Penjumlahan dua matriks.
% C = tambahMatriks(A, B) mengembalikan A + B.
% Melempar error bila ukuran A dan B berbeda.
validasiDimensi(A, B, 'tambah');
C = A + B;
endMari kita bedah baris-baris kode di atas:
- Baris 1 (
function C = tambahMatriks(A, B)): fungsi menerima dua matriks dan mengembalikan satu matriks — bentuk array-in, array-out yang enak dipakai berantai dan diuji. - Baris 5 (
validasiDimensi(A, B, 'tambah')): syarat ukuran diperiksa sebelum menghitung. Bila ukuran berbeda,validasiDimensimelemparerrordan baris 6 tidak pernah tercapai — pengguna mendapat pesan yang jelas, bukan galat teknis dari+. - Baris 6 (
C = A + B;): operator+pada matriks memang menjumlahkan elemen demi elemen; tidak ada loop yang perlu kita tulis.
src/kurangMatriks.m adalah cerminnya: validasiDimensi(A, B, 'kurang') lalu C = A - B;. Keduanya berbagi satu fungsi validasi sehingga aturan “ukuran harus sama” hanya ditulis di satu tempat.
Perkalian Matriks #
Perkalian matriks punya aturan kompatibilitas yang berbeda: jumlah kolom A harus sama dengan jumlah baris B. Matriks 2x3 boleh dikalikan matriks 3x2 dan hasilnya berukuran 2x2. Berikut src/kaliMatriks.m:
function C = kaliMatriks(A, B)
% KALIMATRIKS Perkalian matriks.
% C = kaliMatriks(A, B) mengembalikan A * B.
% Melempar error bila jumlah kolom A tidak sama dengan jumlah baris B.
validasiDimensi(A, B, 'kali');
C = A * B;
endBedahnya singkat karena polanya sama, dengan dua catatan. Pertama, operator * pada matriks adalah perkalian matriks sungguhan — berbeda dari .* yang mengalikan elemen demi elemen; keduanya dibedakan pada chapter Operasi Elemen Array. Kedua, pesan galatnya sengaja spesifik untuk perkalian:
Ukuran tidak kompatibel: 2x2 vs 3x2. Perkalian memerlukan jumlah kolom A sama dengan jumlah baris B.Transpose dan Determinan #
Transpose dan determinan hanya membaca satu matriks. Berikut src/transposeMatriks.m dan src/determinanMatriks.m:
function C = transposeMatriks(A)
% TRANSPOSEMATRIKS Transpose matriks.
% C = transposeMatriks(A) mengembalikan A.' (baris menjadi kolom).
% Semua masukan kalkulator ini bilangan real sehingga operator .' dan
% ' memberi hasil sama; kita memakai .' karena maknanya memang
% transpose murni tanpa konjugasi.
C = A.';
endfunction d = determinanMatriks(A)
% DETERMINANMATRIKS Determinan matriks persegi.
% d = determinanMatriks(A) mengembalikan det(A).
% Melempar error bila A bukan matriks persegi.
validasiPersegi(A);
d = det(A);
endDeterminan hanya terdefinisi untuk matriks persegi. Pemeriksaan itu dipegang src/validasiPersegi.m:
function validasiPersegi(A)
% VALIDASIPERSEGI Memeriksa sebuah matriks berbentuk persegi.
% validasiPersegi(A)
%
% Fungsi ini tidak mengembalikan nilai: bila jumlah baris tidak sama
% dengan jumlah kolom, fungsi melempar error.
[nBaris, nKolom] = size(A);
if nBaris ~= nKolom
error('validasiPersegi:nonPersegi', ...
['Matriks %dx%d bukan persegi. ' ...
'Determinan hanya terdefinisi untuk matriks persegi.'], ...
nBaris, nKolom);
end
endMari kita bedah baris-baris kode di atas:
- Baris 7 (
[nBaris, nKolom] = size(A);): satu panggilansizemengisi kedua ukuran sekaligus — pola standar mengambil dimensi matriks. - Baris 8-13 (
if nBaris ~= nKolom ... end):errordengan identifier'validasiPersegi:nonPersegi'diikuti pesan berformat. Identifier membantu program (dan test) mengenali jenis galat; pesanMatriks 2x3 bukan persegi. ...ditujukan untuk manusia.
Validasi Dimensi dengan Pesan Informatif #
Seluruh aturan ukuran hidup dalam satu fungsi, src/validasiDimensi.m:
function validasiDimensi(A, B, operasi)
% VALIDASIDIMENSI Memeriksa dua matriks layak dioperasikan.
% validasiDimensi(A, B, 'tambah') : ukuran A dan B harus sama
% validasiDimensi(A, B, 'kurang') : ukuran A dan B harus sama
% validasiDimensi(A, B, 'kali') : kolom A harus sama dengan baris B
%
% Fungsi ini tidak mengembalikan nilai: bila ukuran tidak layak,
% fungsi melempar error dengan pesan yang menyebut kedua ukuran.
[nA, mA] = size(A);
[nB, mB] = size(B);
switch operasi
case {'tambah', 'kurang'}
if ~isequal([nA mA], [nB mB])
error('validasiDimensi:ukuran', ...
['Ukuran tidak kompatibel: %dx%d vs %dx%d. ' ...
'Penjumlahan dan pengurangan memerlukan ukuran sama.'], ...
nA, mA, nB, mB);
end
case 'kali'
if mA ~= nB
error('validasiDimensi:ukuran', ...
['Ukuran tidak kompatibel: %dx%d vs %dx%d. ' ...
'Perkalian memerlukan jumlah kolom A sama dengan jumlah baris B.'], ...
nA, mA, nB, mB);
end
otherwise
error('validasiDimensi:operasi', ...
'Operasi tidak dikenal: %s', operasi);
end
endMari kita bedah baris-baris kode di atas:
- Baris 9-10 (
[nA, mA] = size(A);): keempat ukuran diambil di awal sehingga pesan galat bisa menyebut keduanya — pesanUkuran tidak kompatibel: 2x3 vs 2x2jauh lebih bisa ditindaklanjuti daripada galat bawaanError using + Matrix dimensions must agree. - Baris 11 (
switch operasi): satu fungsi melayani tiga operasi.case {'tambah', 'kurang'}pada baris 12 mencocokkan dua nama sekaligus karena syaratnya sama. - Baris 13 (
if ~isequal([nA mA], [nB mB])): kedua ukuran dirangkum sebagai vektor 1x2 lalu dibandingkan sekali — lebih ringkas daripada membandingkannA ~= nB || mA ~= mB. - Baris 14-17 dan 21-24 (gabungan string dalam
error): pesan panjang dirangkai dengan[... ...]dua baris agar sumber mudah dibaca; hasil cetaknya tetap satu baris.
Tabel berikut merangkum seluruh syarat ukuran beserta pesan galatnya:
| Operasi | Syarat | Pesan galat |
|---|---|---|
| tambah/kurang | size(A) sama dengan size(B) | Ukuran tidak kompatibel: 2x2 vs 2x3. Penjumlahan dan pengurangan memerlukan ukuran sama. |
| kali | kolom A = baris B | Ukuran tidak kompatibel: 2x2 vs 3x2. Perkalian memerlukan jumlah kolom A sama dengan jumlah baris B. |
| determinan | A persegi | Matriks 2x3 bukan persegi. Determinan hanya terdefinisi untuk matriks persegi. |
| transpose | tanpa syarat | - |
Menampilkan Hasil dengan Rapi #
Hasil perlu dicetak dengan kolom rata kanan agar mudah dibaca. Seluruh tugas itu dipegang src/tampilkanMatriks.m:
function tampilkanMatriks(label, M)
% TAMPILKANMATRIKS Mencetak matriks dengan kolom rata kanan.
% tampilkanMatriks('Hasil:', M)
%
% Lebar tiap kolom dihitung dari angka terpanjang di kolom tersebut,
% lalu format '%*g' merata-kanankan angka pada lebar itu.
[nBaris, nKolom] = size(M);
% ---- 1. hitung lebar tiap kolom ----
lebar = zeros(1, nKolom);
for j = 1:nKolom
for i = 1:nBaris
w = length(sprintf('%g', M(i, j)));
if w > lebar(j)
lebar(j) = w;
end
end
end
% ---- 2. cetak baris demi baris ----
fprintf('%s\n', label);
for i = 1:nBaris
for j = 1:nKolom
fprintf(' %*g', lebar(j), M(i, j));
end
fprintf('\n');
end
endMari kita bedah baris-baris kode di atas:
- Baris 13 (
w = length(sprintf('%g', M(i, j)));): lebar angka = panjang teksnya.sprintf('%g', 10)menghasilkan'10'sepanjang 2 karakter — format%gjuga memangkas nol buntut sehingga6.0tampil sebagai6. - Baris 14-16 (
if w > lebar(j)):lebar(j)menyimpan angka terpanjang pada kolomj; matriks maksimum 10x10 membuat dua loop ini murah. - Baris 24 (
fprintf(' %*g', lebar(j), M(i, j));): tanda*pada format meminta lebar kolom dari argumen — angka dirata-kanankan pada lebarlebar(j)dengan satu spasi pemisah di depannya. - Baris 26 (
fprintf('\n');): baris baru dicetak setelah satu baris matriks selesai — kita mengendalikan penuh letak baris, berbeda darifprintf('%g', M)yang memproses matriks kolom demi kolom (column-major) sehingga urutannya kacau.
Pemanggilannya dari kalkulator.m cukup satu baris, tampilkanMatriks('Hasil:', hasil);, dan hasil penjumlahan [1 2; 3 4] + [5 6; 7 8] tampil sebagai:
Output yang Dihasilkan:
Hasil:
6 8
10 12Untuk determinan, kalkulator.m memakai satu fprintf('Determinan = %g\n', d) karena hasilnya skalar — pada matriks demo 4 7; 2 6 tercetak Determinan = 10.
Uji Awal Operasi #
Setiap fungsi operasi kini bisa diuji tanpa menu. Berkas tests/uji_operasi.m merangkum kasusnya sebagai tabel: kolom nama, kolom panggilan assert dalam anonymous function:
% ---- kasus nilai: fungsi harus menghasilkan nilai yang benar ----
% Setiap baris: {nama kasus, panggilan yang memakai assert}.
kasus = { ...
'tambah 2x2', @() assert(isequal(tambahMatriks([1 2; 3 4], [5 6; 7 8]), [6 8; 10 12]));
'tambah 2x3', @() assert(isequal(tambahMatriks([1 2 3; 4 5 6], [7 8 9; 10 11 12]), [8 10 12; 14 16 18]));
'kurang 2x2', @() assert(isequal(kurangMatriks([5 6; 7 8], [1 2; 3 4]), [4 4; 4 4]));
'kali 2x2x2x2', @() assert(isequal(kaliMatriks([1 2; 3 4], [5 6; 7 8]), [19 22; 43 50]));
'kali 2x3x3x2', @() assert(isequal(kaliMatriks([1 2 3; 4 5 6], [7 8; 9 10; 11 12]), [58 64; 139 154]));
'kali 1x3x3x1', @() assert(isequal(kaliMatriks([1 2 3], [7; 8; 9]), 50));
'transpose 2x3', @() assert(isequal(transposeMatriks([1 2 3; 4 5 6]), [1 4; 2 5; 3 6]));
'determinan 2x2', @() assert(abs(determinanMatriks([1 2; 3 4]) + 2) < 1e-9);
'determinan 3x3', @() assert(abs(determinanMatriks([2 0 0; 0 3 0; 0 0 4]) - 24) < 1e-9);
'determinan 1x1', @() assert(isequal(determinanMatriks([5]), 5));
};Kasus determinan memakai toleransi 1e-9 daripada isequal karena det menghitung lewat dekomposisi LU — hasil bilangan bulat kecil biasanya eksak, tetapi toleransi membuat test tidak rapuh. Menjalankan berkas dari folder tests/ memberi hasil:
Output yang Dihasilkan:
== uji_operasi.m ==
LULUS: tambah 2x2
LULUS: tambah 2x3
LULUS: kurang 2x2
LULUS: kali 2x2x2x2
LULUS: kali 2x3x3x2
LULUS: kali 1x3x3x1
LULUS: transpose 2x3
LULUS: determinan 2x2
LULUS: determinan 3x3
LULUS: determinan 1x1
LULUS: tambah 2x2+2x3
LULUS: kali 2x2x3x2
LULUS: determinan 2x3
Ringkasan: 13 lulus, 0 gagal (total 13)Tiga baris terakhir adalah kasus galat — dimensi salah yang justru harus melempar error; polanya kita bahas tuntas pada Bagian 4. Mesin hitung kini teruji, tetapi pintu masih terbuka bagi masukan yang salah ketik: teks '1 2; 3 4' belum pernah dibaca dari pengguna. Bagian 3 membangun gerbangnya: parser yang mengubah teks menjadi matriks dengan aman.