BAB 20: Number (Bilangan)
Dalami tipe numerik Python secara menyeluruh — dari integer tanpa batas, floating point dan jebakannya, basis bilangan, notasi eksponensial, hingga bilangan kompleks.
Sepanjang bab-bab sebelumnya, kita sudah bekerja dengan angka tanpa banyak bertanya. Skor peserta kuis disimpan sebagai int, rata-rata dihitung dan hasilnya otomatis menjadi float, lalu f-string memformatnya dengan :.1f. Di BAB 8, tipe numerik dibahas sekilas bersama tipe data lainnya. Tapi sekarang setelah kita mendalami string, list, tuple, set, dan dictionary masing-masing dalam babnya sendiri, angka pantas mendapat perlakuan yang sama.
Python menyediakan tiga tipe numerik bawaan: int, float, dan complex. Ketiganya terlihat sederhana di permukaan, tapi masing-masing punya karakteristik yang menarik — dan beberapa di antaranya bisa menjebak kalau tidak dipahami.
Integer Tanpa Batas
Di banyak bahasa pemrograman, integer punya batas maksimum. C misalnya membatasi int di 2.147.483.647 — lewati angka itu dan programmu akan mengalami overflow. Python tidak punya batasan ini. Integer di Python bisa sebesar yang kamu butuhkan, selama memori komputer masih tersedia.
# kuis.py — integer besar
angka_besar = 99999999999999999999999999999999
print(angka_besar)
print(type(angka_besar))
99999999999999999999999999999999
<class 'int'>
Kemampuan ini mungkin terasa berlebihan untuk program kuis kita, tapi sangat penting di bidang kriptografi dan komputasi ilmiah di mana bilangan besar adalah hal biasa.
Underscore sebagai Pemisah Ribuan
Angka panjang sulit dibaca. Python mengizinkan underscore _ sebagai pemisah visual di dalam literal angka tanpa mengubah nilainya:
# kuis.py — angka dengan underscore
jumlah_pendaftar = 1_250_000
anggaran = 75_000_000
print(jumlah_pendaftar)
print(anggaran)
print(jumlah_pendaftar + anggaran)
1250000
75000000
76250000
Python mengabaikan underscore saat memproses angka — 1_250_000 dan 1250000 adalah nilai yang identik. Underscore hanya untuk mata manusia, dan boleh ditempatkan di posisi mana pun di antara digit.
Basis Bilangan
Secara default, semua literal angka di Python ditulis dalam basis 10 (desimal). Tapi Python juga mendukung tiga basis lain yang sering dipakai di dunia pemrograman: heksadesimal (basis 16), oktal (basis 8), dan biner (basis 2).
# kuis.py — literal berbagai basis
desimal = 200
heksadesimal = 0xC8
oktal = 0o310
biner = 0b11001000
print(f"Desimal: {desimal}")
print(f"Heksadesimal: {heksadesimal}")
print(f"Oktal: {oktal}")
print(f"Biner: {biner}")
Desimal: 200
Heksadesimal: 200
Oktal: 200
Biner: 200
Keempat variabel di atas menyimpan nilai yang sama: 200. Python mengonversi semua basis ke representasi integer internal yang sama. Prefix 0x menandakan heksadesimal, 0o untuk oktal, dan 0b untuk biner.
Konversi Antar Basis
Fungsi bawaan hex(), oct(), dan bin() mengonversi integer ke representasi string basis tertentu:
# kuis.py — konversi basis
skor = 200
print(f"Hex: {hex(skor)}")
print(f"Oct: {oct(skor)}")
print(f"Bin: {bin(skor)}")
Hex: 0xc8
Oct: 0o310
Bin: 0b11001000
Hasil konversi berupa string (perhatikan tipe str), bukan angka. Ini karena representasi seperti 0xc8 hanya bermakna sebagai notasi penulisan — secara internal Python tetap menyimpan nilainya sebagai integer biasa.
Untuk arah sebaliknya — mengonversi string representasi basis ke integer — gunakan int() dengan parameter base:
# kuis.py — string basis ke integer
dari_hex = int("C8", base=16)
dari_oct = int("310", base=8)
dari_bin = int("11001000", base=2)
print(dari_hex)
print(dari_oct)
print(dari_bin)
200
200
200
Format String untuk Basis
F-string juga mendukung format specifier untuk menampilkan angka dalam basis tertentu tanpa prefix:
# kuis.py — format specifier basis
skor = 200
print(f"Desimal: {skor:d}")
print(f"Heksadesimal: {skor:x}")
print(f"Oktal: {skor:o}")
print(f"Biner: {skor:b}")
Desimal: 200
Heksadesimal: c8
Oktal: 310
Biner: 11001000
Specifier :x menghasilkan huruf kecil. Gunakan :X untuk huruf kapital (C8 alih-alih c8). Ini berguna saat kamu perlu menampilkan warna hex, alamat memori, atau kode biner dalam output yang rapi.
Float dan Presisi
Float menyimpan bilangan desimal menggunakan standar IEEE 754 dengan presisi 64-bit. Untuk mayoritas kebutuhan — menghitung rata-rata skor, persentase kelulusan, nilai diskon — presisi ini lebih dari cukup. Tapi ada satu gotcha klasik yang sudah menjebak banyak programmer.
# kuis.py — gotcha presisi float
hasil = 0.1 + 0.2
print(hasil)
print(hasil == 0.3)
0.30000000000000004
False
Hasilnya bukan 0.3 yang kita harapkan, melainkan 0.30000000000000004. Ini bukan bug Python — ini adalah keterbatasan fundamental dari cara komputer merepresentasikan bilangan desimal dalam biner. Angka 0.1 tidak bisa direpresentasikan secara persis dalam biner, sama seperti 1/3 tidak bisa ditulis secara persis dalam desimal (0.333…).
Jangan pernah membandingkan dua float dengan == secara langsung jika nilainya berasal dari perhitungan. Gunakan pembulatan atau toleransi (epsilon) untuk perbandingan yang aman.
Pembulatan
Python menyediakan beberapa cara untuk membulatkan float:
# kuis.py — teknik pembulatan
import math
rata_rata = 79.456
# round() — pembulatan standar
print(f"round 2 desimal: {round(rata_rata, 2)}")
print(f"round 1 desimal: {round(rata_rata, 1)}")
print(f"round bulat: {round(rata_rata)}")
# math.floor() — bulatkan ke bawah
print(f"floor: {math.floor(rata_rata)}")
# math.ceil() — bulatkan ke atas
print(f"ceil: {math.ceil(rata_rata)}")
round 2 desimal: 79.46
round 1 desimal: 79.5
round bulat: 79
floor: 79
ceil: 80
round() menggunakan strategi banker’s rounding (pembulatan ke genap terdekat) untuk angka yang tepat di tengah. Misalnya round(0.5) menghasilkan 0, bukan 1 — karena 0 adalah genap terdekat. round(1.5) menghasilkan 2. Perilaku ini mungkin mengejutkan, tapi secara statistik lebih akurat untuk kumpulan data besar.
math.floor() dan math.ceil() selalu membulatkan ke satu arah — floor ke bawah, ceil ke atas — dan mengembalikan int, bukan float.
Format Tampilan Float
Saat yang penting adalah tampilan bukan nilai internal, gunakan format specifier:
# kuis.py — format tampilan float
rata_rata = 79.456
persentase = 0.7946
print(f"Rata-rata: {rata_rata:.1f}")
print(f"Persentase: {persentase:.2%}")
print(f"Lebar 10 karakter: {rata_rata:10.2f}")
Rata-rata: 79.5
Persentase: 79.46%
Lebar 10 karakter: 79.46
Specifier :.1f menampilkan 1 digit di belakang koma, :.2% mengalikan dengan 100 dan menambahkan tanda persen, dan :10.2f mengatur lebar total 10 karakter dengan 2 desimal — teknik yang sudah kita pakai di BAB 19 untuk merapikan output tabel.
Notasi Eksponensial
Float bisa ditulis dalam notasi eksponensial (scientific notation) menggunakan huruf e — berguna untuk angka yang sangat besar atau sangat kecil:
# kuis.py — notasi eksponensial
jarak_matahari = 1.496e11 # 149.600.000.000 meter
massa_elektron = 9.109e-31 # 0.0000000000000000000000000000009109 kg
print(jarak_matahari)
print(massa_elektron)
print(type(jarak_matahari))
149600000000.0
9.109e-31
<class 'float'>
Notasi 1.496e11 berarti 1.496 dikali 10 pangkat 11. Notasi 9.109e-31 berarti 9.109 dikali 10 pangkat minus 31. Keduanya menghasilkan float.
Python juga menampilkan angka yang sangat besar atau kecil dalam notasi eksponensial secara otomatis:
# kuis.py — Python otomatis pakai notasi eksponensial
hasil = 0.000000001
print(hasil)
besar = 10 ** 20 * 1.5
print(besar)
1e-09
1.5e+20
Konversi Tipe Numerik
Di BAB 8 kita sudah menyinggung int() dan float() untuk konversi. Berikut gambaran lengkap bagaimana ketiga tipe numerik saling mengonversi:
# kuis.py — konversi antar tipe numerik
# float ke int (memotong desimal, bukan membulatkan)
skor_float = 85.7
skor_int = int(skor_float)
print(f"int(85.7) = {skor_int}")
# int ke float
jumlah = 17
jumlah_float = float(jumlah)
print(f"float(17) = {jumlah_float}")
# string ke numerik
input_skor = "92"
input_rata = "85.5"
print(f"int('92') = {int(input_skor)}")
print(f"float('85.5') = {float(input_rata)}")
# int/float ke complex
bilangan = complex(85, 0)
print(f"complex(85, 0) = {bilangan}")
int(85.7) = 85
float(17) = 17.0
int('92') = 92
float('85.5') = 85.5
complex(85, 0) = (85+0j)
Perhatikan bahwa int() memotong desimal, bukan membulatkan. int(85.7) menghasilkan 85, bukan 86. Kalau kamu ingin membulatkan sebelum mengonversi, gunakan round() terlebih dahulu: int(round(85.7)) menghasilkan 86.
Konversi dari complex ke int atau float tidak diizinkan — Python akan melempar TypeError. Ini masuk akal karena bilangan kompleks punya dua komponen (real dan imajiner), dan tidak ada cara yang jelas untuk “menyusutkannya” menjadi satu angka.
Bilangan Kompleks
Bilangan kompleks terdiri dari dua bagian: komponen real dan komponen imajiner. Di Python, bagian imajiner ditandai dengan suffix j (bukan i seperti di matematika).
# simulasi.py — bilangan kompleks dasar
impedansi = 120 + 3j
print(f"Bilangan: {impedansi}")
print(f"Real: {impedansi.real}")
print(f"Imajiner: {impedansi.imag}")
print(f"Tipe: {type(impedansi)}")
Bilangan: (120+3j)
Real: 120.0
Imajiner: 3.0
Tipe: <class 'complex'>
Properti .real dan .imag selalu mengembalikan float, meskipun kamu menuliskan bagian real dan imajiner sebagai integer.
Operasi Aritmatika Complex
Bilangan kompleks mendukung operasi aritmatika standar, termasuk penjumlahan, pengurangan, perkalian, dan pembagian:
# simulasi.py — aritmatika bilangan kompleks
z1 = 3 + 4j
z2 = 1 - 2j
print(f"z1 + z2 = {z1 + z2}")
print(f"z1 - z2 = {z1 - z2}")
print(f"z1 * z2 = {z1 * z2}")
print(f"z1 / z2 = {z1 / z2}")
z1 + z2 = (4+2j)
z1 - z2 = (2+6j)
z1 * z2 = (11-2j)
z1 / z2 = (-1+2j)
Bilangan kompleks juga bisa dicampur dengan integer dan float dalam operasi aritmatika. Python otomatis mengonversi tipe yang “lebih sempit” ke complex:
# simulasi.py — complex dengan tipe lain
z = 5 + 3j
skala = 2
print(f"z * 2 = {z * skala}")
print(f"z + 10 = {z + 10}")
print(f"z + 1.5 = {z + 1.5}")
z * 2 = (10+6j)
z + 10 = (15+3j)
z + 1.5 = (6.5+3j)
Fungsi complex() juga bisa digunakan untuk membuat bilangan kompleks dari dua argumen terpisah:
# simulasi.py — konstruktor complex()
z = complex(120, 3)
print(z)
(120+3j)
Bilangan kompleks jarang dipakai dalam pemrograman sehari-hari, tapi menjadi penting di bidang seperti pemrosesan sinyal digital, analisis rangkaian listrik, dan simulasi fisika. Mengetahui bahwa Python mendukungnya secara native — tanpa perlu library tambahan — adalah nilai plus dibanding banyak bahasa lain.
Fungsi Matematika Bawaan
Selain operator aritmatika yang sudah kita bahas di BAB 9, Python menyediakan beberapa fungsi bawaan yang berguna untuk operasi numerik:
# kuis.py — fungsi matematika bawaan
skor_peserta = [85, 72, 91, 68, 77]
print(f"Terkecil: {min(skor_peserta)}")
print(f"Terbesar: {max(skor_peserta)}")
print(f"Jumlah: {sum(skor_peserta)}")
print(f"Rata-rata: {sum(skor_peserta) / len(skor_peserta):.1f}")
# abs() untuk nilai absolut
selisih = 72 - 91
print(f"Selisih: {selisih}, Absolut: {abs(selisih)}")
# pow() — alternatif dari operator **
print(f"2 pangkat 10: {pow(2, 10)}")
print(f"Sama dengan: {2 ** 10}")
Terkecil: 68
Terbesar: 91
Jumlah: 393
Rata-rata: 78.6
Selisih: -19, Absolut: 19
2 pangkat 10: 1024
Sama dengan: 1024
Fungsi min(), max(), dan sum() sudah kita gunakan sejak BAB 14 untuk mengolah list. Fungsi-fungsi ini juga menerima beberapa argumen langsung: max(85, 72, 91) bekerja sama baiknya dengan max([85, 72, 91]).
Modul math
Untuk operasi matematika yang lebih lanjut, Python menyediakan modul math di standard library:
# kuis.py — modul math
import math
# akar kuadrat
print(f"Akar 144: {math.sqrt(144)}")
# logaritma
print(f"log10(1000): {math.log10(1000)}")
print(f"log2(1024): {math.log2(1024)}")
# konstanta
print(f"Pi: {math.pi}")
print(f"e: {math.e}")
print(f"inf: {math.inf}")
Akar 144: 12.0
log10(1000): 3.0
log2(1024): 10.0
Pi: 3.141592653589793
e: 2.718281828459045
inf: inf
math.inf merepresentasikan tak hingga positif — berguna sebagai nilai awal saat mencari minimum, atau sebagai sentinel value. math.pi dan math.e adalah konstanta matematika dengan presisi float maksimum.
Latihan
Tiga tantangan yang menggabungkan konsep bilangan dengan materi dari bab-bab sebelumnya:
-
Buat dictionary
skor_peserta = {"Rina": 85, "Budi": 72, "Sari": 91, "Dimas": 68}. Hitung rata-rata skor semua peserta menggunakansum()danlen(). Tampilkan rata-rata dengan 2 digit desimal. Kemudian tampilkan berapa persen peserta yang skornya di atas rata-rata, juga dengan 2 digit desimal menggunakan format specifier:.2%. -
Konversi angka
255ke representasi heksadesimal, oktal, dan biner menggunakan fungsi bawaan Python. Kemudian balikkan prosesnya: konversi string"FF"dari heksadesimal,"377"dari oktal, dan"11111111"dari biner kembali ke integer. Verifikasi bahwa semua hasilnya sama. -
Buat program yang mendemonstrasikan masalah presisi float. Hitung
0.1 + 0.1 + 0.1dan bandingkan hasilnya dengan0.3. Cetak hasil perbandingan langsung (==), lalu buat perbandingan yang aman menggunakanround()pada kedua sisi dengan presisi 10 digit desimal. Cetak kedua hasil perbandingan dan jelaskan perbedaannya lewat komentar di kode.
Kita sudah mendalami semua tipe data bawaan Python — dari string dan koleksi di bab-bab sebelumnya, hingga numerik di bab ini. Sekarang kamu punya pemahaman lengkap tentang data apa saja yang bisa diolah Python dan bagaimana perilaku masing-masing tipe. Tapi sejauh ini semua kode masih berupa satu blok panjang dari atas ke bawah. Semakin kompleks programnya, semakin sulit kode seperti itu dikelola dan digunakan kembali. Bagaimana kalau ada cara untuk memecah kode menjadi potongan-potongan kecil yang bisa dipanggil kapan saja dari mana saja?