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,
  • tampilkanMatriks untuk 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:

matlab
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;
end

Mari kita bedah baris-baris kode di atas:

  1. 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.
  2. Baris 5 (validasiDimensi(A, B, 'tambah')): syarat ukuran diperiksa sebelum menghitung. Bila ukuran berbeda, validasiDimensi melempar error dan baris 6 tidak pernah tercapai — pengguna mendapat pesan yang jelas, bukan galat teknis dari +.
  3. 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:

matlab
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;
end

Bedahnya 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:

text
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:

matlab
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.';
end
matlab
function 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);
end

Determinan hanya terdefinisi untuk matriks persegi. Pemeriksaan itu dipegang src/validasiPersegi.m:

matlab
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
end

Mari kita bedah baris-baris kode di atas:

  1. Baris 7 ([nBaris, nKolom] = size(A);): satu panggilan size mengisi kedua ukuran sekaligus — pola standar mengambil dimensi matriks.
  2. Baris 8-13 (if nBaris ~= nKolom ... end): error dengan identifier 'validasiPersegi:nonPersegi' diikuti pesan berformat. Identifier membantu program (dan test) mengenali jenis galat; pesan Matriks 2x3 bukan persegi. ... ditujukan untuk manusia.

Validasi Dimensi dengan Pesan Informatif #

Seluruh aturan ukuran hidup dalam satu fungsi, src/validasiDimensi.m:

matlab
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
end

Mari kita bedah baris-baris kode di atas:

  1. Baris 9-10 ([nA, mA] = size(A);): keempat ukuran diambil di awal sehingga pesan galat bisa menyebut keduanya — pesan Ukuran tidak kompatibel: 2x3 vs 2x2 jauh lebih bisa ditindaklanjuti daripada galat bawaan Error using + Matrix dimensions must agree.
  2. Baris 11 (switch operasi): satu fungsi melayani tiga operasi. case {'tambah', 'kurang'} pada baris 12 mencocokkan dua nama sekaligus karena syaratnya sama.
  3. Baris 13 (if ~isequal([nA mA], [nB mB])): kedua ukuran dirangkum sebagai vektor 1x2 lalu dibandingkan sekali — lebih ringkas daripada membandingkan nA ~= nB || mA ~= mB.
  4. 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:

OperasiSyaratPesan galat
tambah/kurangsize(A) sama dengan size(B)Ukuran tidak kompatibel: 2x2 vs 2x3. Penjumlahan dan pengurangan memerlukan ukuran sama.
kalikolom A = baris BUkuran tidak kompatibel: 2x2 vs 3x2. Perkalian memerlukan jumlah kolom A sama dengan jumlah baris B.
determinanA persegiMatriks 2x3 bukan persegi. Determinan hanya terdefinisi untuk matriks persegi.
transposetanpa syarat-

Menampilkan Hasil dengan Rapi #

Hasil perlu dicetak dengan kolom rata kanan agar mudah dibaca. Seluruh tugas itu dipegang src/tampilkanMatriks.m:

matlab
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
end

Mari kita bedah baris-baris kode di atas:

  1. Baris 13 (w = length(sprintf('%g', M(i, j)));): lebar angka = panjang teksnya. sprintf('%g', 10) menghasilkan '10' sepanjang 2 karakter — format %g juga memangkas nol buntut sehingga 6.0 tampil sebagai 6.
  2. Baris 14-16 (if w > lebar(j)): lebar(j) menyimpan angka terpanjang pada kolom j; matriks maksimum 10x10 membuat dua loop ini murah.
  3. Baris 24 (fprintf(' %*g', lebar(j), M(i, j));): tanda * pada format meminta lebar kolom dari argumen — angka dirata-kanankan pada lebar lebar(j) dengan satu spasi pemisah di depannya.
  4. Baris 26 (fprintf('\n');): baris baru dicetak setelah satu baris matriks selesai — kita mengendalikan penuh letak baris, berbeda dari fprintf('%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:

text
Hasil:
  6  8
 10 12

Untuk 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:

matlab
% ---- 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:

text
== 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.