Algoritma adalah rangkaian keputusan: tambah satu elemen, geser bit, bandingkan dua nilai, kombinasikan kondisi. C++ menyediakan kumpulan operator yang kaya untuk mengekspresikan keputusan-keputusan tersebut secara ringkas. Pada Chapter ini kita akan mempelajari operator aritmetika, perbandingan, logika, bitwise, dan shift — khususnya bitwise dan shift yang sangat sering dipakai dalam algoritma optimasi bitmask, struktur fenwick tree, dan representasi himpunan.

Operator Aritmetika #

Operator aritmetika bekerja pada tipe numerik. Untuk dua operan bertipe int, pembagian selalu menghasilkan int dengan membuang pecahan — perilaku yang sering membingungkan pemula.

OperatorMaknaContohHasil
+Penjumlahan17 + 522
-Pengurangan17 - 512
*Perkalian17 * 585
/Pembagian17 / 53
%Sisa bagi17 % 52

Mekanisme: Integer Division vs Floating-Point Division #

Ketika kedua operan bertipe integer, C++ melakukan integer division: hasil dibuang pecahannya, bukan dibulatkan. Sisa bagi ditangani terpisah oleh %. Operator % hanya berlaku untuk tipe integer, tidak untuk double.

Kode: Aritmetika Dasar #

cpp
#include <iostream>

int main() {
    int a = 17, b = 5;
    std::cout << "a + b = " << a + b << '\n';
    std::cout << "a - b = " << a - b << '\n';
    std::cout << "a * b = " << a * b << '\n';
    std::cout << "a / b = " << a / b << '\n';   // integer division
    std::cout << "a % b = " << a % b << '\n';    // sisa bagi
    return 0;
}

Output yang Dihasilkan:

text
a + b = 22
a - b = 12
a * b = 85
a / b = 3
a % b = 2
  1. Baris a / b: karena a dan b bertipe int, hasil 17/5 dipotong menjadi 3 tanpa pembulatan.
  2. Baris a % b: menghasilkan sisa 2 karena 5 * 3 + 2 = 17.

Operator Bitwise dan Shift #

Operator bitwise memanipulasi nilai pada level bit. Banyak algoritma DSA memakainya: bitmask DP, pengecekan subset himpunan, dan operasi ringan pada fenwick tree atau segment tree. Operator shift (<<, >>) sangat berguna untuk mengalikan atau membagi dengan pangkat dua secara efisien.

OperatorMaknaContoh (x=0b1100, y=0b1010)Hasil
&AND bitwisex & y0b1000 = 8
|OR bitwisex | y0b1110 = 14
^XOR bitwisex ^ y0b0110 = 6
~NOT (invert)~xkomplemen
<<Shift kirix << 20b110000 = 48
>>Shift kananx >> 10b0110 = 6

Mekanisme: Shift sebagai Pangkat Dua #

x << n setara dengan x * 2^n untuk unsigned integer, dan x >> n setara dengan x / 2^n (pembagian bulat). Operasi shift lebih cepat daripada perkalian/pembagian biasa karena langsung berjalan pada register CPU.

Kode: Bitwise dan Shift #

cpp
#include <iostream>

int main() {
    unsigned int x = 0b1100;   // 12
    unsigned int y = 0b1010;   // 10
    std::cout << "x & y  = " << (x & y) << '\n';
    std::cout << "x | y  = " << (x | y) << '\n';
    std::cout << "x ^ y  = " << (x ^ y) << '\n';
    std::cout << "x << 2 = " << (x << 2) << '\n';
    std::cout << "x >> 1 = " << (x >> 1) << '\n';
    return 0;
}

Output yang Dihasilkan:

text
x & y  = 8
x | y  = 14
x ^ y  = 6
x << 2 = 48
x >> 1 = 6
  1. Baris x & y: AND bitwise — bit hasil 1 hanya bila kedua operan 1.
  2. Baris x ^ y: XOR — bit hasil 1 bila kedua operan berbeda.
  3. Baris x << 2: shift kiri 2 posisi = kalikan dengan 4 = 12 * 4 = 48.
  4. Baris x >> 1: shift kanan 1 posisi = bagi 2 = 12 / 2 = 6.

Pola Bitmask untuk DSA #

Empat operasi dasar pada bitmask sering muncul di soal himpunan atau dynamic programming dengan state bitmask: cek bit, nyalakan bit, matikan bit, dan balik bit.

Kode: Operasi Bitmask #

cpp
#include <iostream>
#include <bitset>

int main() {
    unsigned int mask = 0b0100;             // bit ke-2
    unsigned int n = 0b1011;                 // bit aktif: 0, 1, 3
    std::cout << "mask      = " << std::bitset<8>(mask) << '\n';
    std::cout << "n         = " << std::bitset<8>(n) << '\n';

    bool on = (n & mask) != 0;               // cek bit ke-2
    std::cout << "bit ke-2? = " << std::boolalpha << on << '\n';

    unsigned int set = n | mask;             // nyalakan bit ke-2
    std::cout << "set       = " << std::bitset<8>(set) << '\n';

    unsigned int clear = set & ~mask;        // matikan bit ke-2 di 'set'
    std::cout << "clear     = " << std::bitset<8>(clear) << '\n';

    unsigned int toggle = n ^ mask;          // balik bit ke-2
    std::cout << "toggle    = " << std::bitset<8>(toggle) << '\n';

    int popcount = __builtin_popcount(n);    // jumlah bit 1
    std::cout << "popcount  = " << popcount << '\n';
    return 0;
}

Output yang Dihasilkan:

text
mask      = 00000100
n         = 00001011
bit ke-2? = false
set       = 00001111
clear     = 00001011
toggle    = 00001111
popcount  = 3
  1. Baris bool on = (n & mask) != 0;: n & mask akan 0 bila bit ke-2 tidak aktif; kita bandingkan dengan 0 agar hasilnya bool. Tanpa pembanding, hasil integer 0/non-nol bisa salah ditafsirkan.
  2. Baris n | mask: OR bitwise menyalakan bit yang 1 di mask tanpa mengubah bit lain.
  3. Baris set & ~mask: NOT ~mask membalik semua bit, lalu AND mematikan bit ke-2.
  4. Baris n ^ mask: XOR membalik bit ke-2. Bila awalnya 0, jadi 1; bila awalnya 1, jadi 0.
  5. Baris __builtin_popcount(n): bawaan GCC/Clang yang menghitung jumlah bit 1 (popcount). Standar C++20 menyediakan std::popcount di header <bit>.

Operator Perbandingan, Logika, dan Ternary #

Operator perbandingan menghasilkan bool. Operator logika mengkombinasikan bool dengan short-circuit: bila operan kiri sudah menentukan hasil, operan kanan tidak dievaluasi.

OperatorMaknaShort-circuit
&&AND logikaBerhenti bila kiri false
||OR logikaBerhenti bila kiri true
!NOTMembalik bool

Kode: Perbandingan, Logika, dan Augmented Assignment #

cpp
#include <iostream>

int main() {
    bool aktif = true;
    int nilai = 75;
    bool lulus = aktif && (nilai >= 70);    // true && true
    std::cout << "lulus = " << std::boolalpha << lulus << '\n';

    int total = 100;
    total += 50;        // total = 150
    total <<= 1;        // total = 300 (shift kiri = kali 2)
    std::cout << "total = " << total << '\n';

    int a = 17, b = 5;
    int maks = (a > b) ? a : b;             // ternary
    std::cout << "maks  = " << maks << '\n';
    return 0;
}

Output yang Dihasilkan:

text
lulus = true
total = 300
maks  = 17
  1. Baris aktif && (nilai >= 70): jika aktif adalah false, ekspresi (nilai >= 70) tidak dievaluasi sama sekali. Perilaku ini bermanfaat saat operan kanan memanggil fungsi yang berat atau mengakses pointer yang mungkin null.
  2. Baris total <<= 1: augmented assignment gabungan dengan shift — ekuivalen dengan total = total << 1 yaitu menggandakan nilai.
  3. Baris (a > b) ? a : b: ternary operator mengembalikan a bila kondisi benar, b bila salah. Sering dipakai untuk memilih nilai tanpa blok if/else penuh.

Precedence dan Associativity #

Precedence menentukan urutan evaluasi saat beberapa operator muncul dalam satu ekspresi tanpa tanda kurung. Tabel berikut menampilkan beberapa precedence yang paling sering keliru.

PrecedenceOperatorAsosiativitas
Tinggi:: (scope)—
++ -- ! ~ (unary)kanan-ke-kiri
* / %kiri-ke-kanan
+ -kiri-ke-kanan
<< >>kiri-ke-kanan
< <= > >=kiri-ke-kanan
== !=kiri-ke-kanan
&kiri-ke-kanan
^kiri-ke-kanan
|kiri-ke-kanan
&&kiri-ke-kanan
||kiri-ke-kanan
Rendah?: = += <<=kanan-ke-kiri

Ringkasan #

  • Operator aritmetika pada int melakukan integer division; gunakan cast bila butuh pecahan.
  • Bitwise dan shift adalah pondasi algoritma bitmask; kuasai empat pola: cek, set, clear, toggle.
  • && dan || mengevaluasi short-circuit — manfaatkan untuk pengecekan pointer null sebelum akses.
  • Tanda kurung selalu lebih murah daripada debugging precedence; pakailah saat ragu.