Fungsi y = f(x) adalah jantung matematika: input → output. Di episode ini kalian memahami jenis-jenis grafik — linear, kuadrat, eksponensial, logaritma — serta notasi sigma dan pi, dan menghubungkannya dengan Big-O notation di coding.

Setelah di episode 3 kita memperkuat arithmetic dan aljabar dasar — operator precedence, pecahan, persentase, dan persamaan linear — pada episode ini kita naik satu level ke fungsi. Fungsi y = f(x) adalah konsep paling fundamental dalam matematika: ia menerima input, memprosesnya, dan menghasilkan output. Setiap fungsi dalam kode kalian adalah fungsi matematika — dari len() hingga sort().
Mengapa harus memahami grafik? Karena grafik memberikan intuisi visual tentang perilaku fungsi — apakah ia tumbuh cepat (eksponensial), lambat (logaritma), atau konstan (linear). Ketika kalian melihat kode yang memanggil fungsi secara berulang dalam loop bersarang, kalian seharusnya langsung bisa memvisualisasikan pertumbuhan eksponensialnya — dan itulah yang membedakan programmer yang sadar kompleksitas dari yang tidak.
Fungsi f: A → B memetakan setiap elemen dari domain A ke exactly satu elemen dari codomain B:
def kuadrat(x: float) -> float:
"""f(x) = x² — setiap input menghasilkan satu output."""
return x ** 2
def abs_val(x: float) -> float:
"""f(x) = |x| — fungsi nilai absolut."""
return abs(x)
# Domain: semua bilangan real (float)
# Range kuadrat: [0, ∞) — tidak pernah negatif
# Range abs_val: [0, ∞) — tidak pernah negatif
for x in [-3, -1, 0, 2, 5]:
print(f"f({x}) = {kuadrat(x)}")Setiap fungsi dalam kode punya domain (tipe input yang valid) dan range (tipe output yang mungkin). Memahami ini membantu kalian menulis validasi dan handle edge cases:
import math
def akar_kuadrat(x: float) -> float:
"""Domain: x ≥ 0. Range: [0, ∞)."""
if x < 0:
raise ValueError(f"Domain error: {x} < 0")
return math.sqrt(x)
def logaritma(x: float) -> float:
"""Domain: x > 0. Range: (-∞, ∞)."""
if x <= 0:
raise ValueError(f"Domain error: {x} ≤ 0")
return math.log(x)
# Contoh validasi domain
print(akar_kuadrat(16)) # 4.0
print(logaritma(100)) # 4.605...Grafik garis lurus — laju perubahan konstan. Muncul dalam pricing model, konversi satuan, dan interpolasi:
def linear(x: float, m: float = 2, c: float = 1) -> float:
return m * x + c
# Contoh: biaya laundry = Rp 5000/kg + Rp 10000 biaya antar
# f(kg) = 5000*kg + 10000
for kg in [1, 3, 5, 10]:
print(f"{kg}kg = Rp {5000*kg + 10000:,}")Parabola — muncul dalam projectile motion, area, dan optimasi quadratic:
import math
def kuadrat(x: float, a: float = 1, b: float = 0, c: float = 0) -> float:
return a * x**2 + b * x + c
# Contoh: tinggi projectile — h(t) = -4.9t² + v₀t + h₀
def tinggi_projectile(t: float, v0: float = 50, h0: float = 0) -> float:
return -4.9 * t**2 + v0 * t + h0
# Cari waktu sampai puncak: t = v0 / (2 * 4.9)
waktu_puncak = 50 / (2 * 4.9)
tinggi_maks = tinggi_projectile(waktu_puncak)
print(f"Puncak pada t={waktu_puncak:.2f}s, tinggi={tinggi_maks:.2f}m")Tumbuh (atau decaying) sangat cepat — muncul dalam compound interest, radioactive decay, dan population growth:
import math
def eksponensial(x: float, a: float = 1, b: float = math.e) -> float:
return a * b**x
# Compound interest: A = P(1 + r)^t
def compound_interest(principal: float, rate: float, years: float) -> float:
return principal * (1 + rate)**years
# Investasi Rp 10 juta, bunga 8%/tahun
for t in [1, 5, 10, 20, 30]:
hasil = compound_interest(10_000_000, 0.08, t)
print(f"Tahun {t:>2}: Rp {hasil:,.0f}")
# Perbandingan pertumbuhan
print(f"\nPerbandingan pada x=10:")
print(f" Linear (2x+1): {2*10 + 1}")
print(f" Kuadrat (x²): {10**2}")
print(f" Eksponensial (2ˣ): {2**10}")Kebalikan dari eksponensial — tumbuh sangat lambat. Logaritma adalah fondasi dari binary search O(log n):
import math
# Logaritma basis-2: berapa kali 2 harus dikalikan untuk mencapai x?
print(f"log₂(8) = {math.log2(8)}") # 3.0
print(f"log₂(1024) = {math.log2(1024)}") # 10.0
# Binary search: dari 1 juta data, cukup ~20 langkah
def binary_search_steps(n: int) -> int:
"""Berapa langkah binary search untuk n elemen."""
return math.ceil(math.log2(n))
print(f"Binary search 1.000.000 data: ~{binary_search_steps(1_000_000)} langkah")
print(f"Binary search 4.000.000.000 data: ~{binary_search_steps(4_000_000_000)} langkah")
# Perbandingan pertumbuhan
print(f"\nNilai pada x=100:")
print(f" Linear (x): 100")
print(f" Kuadrat (x²): {100**2}")
print(f" Eksponensial (2ˣ): {2**20} (20 saja sudah terlalu besar!)")
print(f" Logaritma (log₂x): {math.log2(100):.1f}")Notasi sigma adalah shorthand untuk menjumlahkan deret — representasi matematika dari sum():
def sigma_manual(n: int, fungsi) -> float:
"""Σ f(i) dari i=1 sampai n."""
return sum(fungsi(i) for i in range(1, n + 1))
# Σ i² dari 1 sampai 5 = 1+4+9+16+25 = 55
print(f"Σ i² (i=1..5) = {sigma_manual(5, lambda i: i**2)}")
# Rumus tertutup: Σ i² = n(n+1)(2n+1)/6
def sigma_kuadrat_tertutup(n: int) -> int:
return n * (n + 1) * (2 * n + 1) // 6
print(f"Rumus tertutup: {sigma_kuadrat_tertutup(5)}")Notasi pi adalah shorthand untuk mengalikan deret — seperti reduce() dengan operator multiply:
from math import prod
# Π i dari 1 sampai 5 = 1×2×3×4×5 = 120 (faktorial)
print(f"5! = {prod(range(1, 6))}")
# Faktorial dengan loop — untuk memahami apa yang dilakukan prod()
def faktorial(n: int) -> int:
result = 1
for i in range(1, n + 1):
result *= i
return result
print(f"10! = {faktorial(10):,}")Jenis fungsi di atas secara langsung berkaitan dengan klasifikasi kompleksitas:
| Jenis Fungsi | Kompleksitas | Contoh dalam Kode |
|---|---|---|
| Konstan f(x) = c | O(1) | Akses array dengan indeks |
| Linear f(x) = mx | O(n) | Linear search, single loop |
| Kuadrat f(x) = ax² | O(n²) | Nested loop, bubble sort |
| Eksponensial f(x) = bˣ | O(2ⁿ) | Brute-force subset enumeration |
| Logaritma f(x) = log x | O(log n) | Binary search |
Ketika kalian melihat loop bersarang (nested loop), itu grafik kuadrat — input 2x menghasilkan waktu 4x. Ketika kalian melihat loop yang membagi input dua kali lipat setiap iterasi, itu grafik logaritma — input 2x hanya menambah 1 iterasi.
import time
def linear_search(arr, target):
"""O(n) — linear."""
for item in arr:
if item == target:
return True
return False
def binary_search(arr, target):
"""O(log n) — logaritma."""
lo, hi = 0, len(arr) - 1
while lo <= hi:
mid = (lo + hi) // 2
if arr[mid] == target:
return True
elif arr[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return False
# Bandingkan waktu eksekusi
data = list(range(10_000_000))
target = 9_999_999
start = time.perf_counter()
linear_search(data, target)
t_linear = time.perf_counter() - start
start = time.perf_counter()
binary_search(data, target)
t_binary = time.perf_counter() - start
print(f"Linear: {t_linear:.4f}s")
print(f"Binary: {t_binary:.6f}s")
print(f"Binary {t_linear/t_binary:.0f}x lebih cepat!")Tip
Grafik eksponensial tumbuh sangat cepat: 2^30 ≈ 1 miliar. Jika kode kalian punya kompleksitas eksponensial, input hanya 30 sudah membutuhkan miliaran operasi — terlalu lama untuk production. Selalu cari algoritma dengan kompleksitas lebih rendah.
Inti yang harus dibawa pulang:
y = f(x) memetakan input ke output; domain dan range menentukan batasan validasi.sum(); notasi pi (Π) adalah perkalian berulang.Di episode 5 selanjutnya kita akan memasuki discrete mathematics — mulai dari logika proposisional (boolean logic): truth table, AND/OR/NOT/XOR, dan bagaimana ini menjadi fondasi dari if/else, SQL WHERE clause, dan regex. Dunia discrete math adalah di mana matematika dan programming paling erat berhubungan!