Memilih dtype bukan hanya soal kebenaran hitungan, tetapi juga keputusan performa: dtype menentukan itemsize, dan itemsize menentukan nbytes seluruh array. Tipe yang terlalu besar memboroskan memori dan bandwidth; tipe yang terlalu kecil memangkas biaya tetapi menuntut kompromi jangkauan atau presisi.
Bab ini menyusun pedoman praktisnya: batas tiap tipe, perbandingan kebutuhan memori per juta elemen, kasus khas data 0-255, serta kapan float32 cukup dan kapan harus mundur ke float64.
Jangkauan dan Batas Tiap Tipe #
Modul NumPy menyediakan inspektur bawaan: np.iinfo untuk tipe bulat dan np.finfo untuk tipe float. Keduanya mengembalikan nilai yang deterministik, sehingga layak dijadikan blok uji:
import numpy as np
print("int8 :", np.iinfo(np.int8).min, "sampai", np.iinfo(np.int8).max)
print("uint8:", np.iinfo(np.uint8).min, "sampai", np.iinfo(np.uint8).max)
print("int32:", np.iinfo(np.int32).min, "sampai", np.iinfo(np.int32).max)
print("eps float32:", np.finfo(np.float32).eps)
print("eps float64:", np.finfo(np.float64).eps)Output yang Dihasilkan:
int8 : -128 sampai 127
uint8: 0 sampai 255
int32: -2147483648 sampai 2147483647
eps float32: 1.1920929e-07
eps float64: 2.220446049250313e-16Cara membacanya:
- Baris 3-5 (
np.iinfo(...)): atributmindanmaxmenunjukkan jangkauan aman tiap tipe bulat; nilai di luar batas ini memicu overflow. - Baris 6-7 (
np.finfo(...).eps):epsadalah jarak antara 1.0 dan nilai float terdekat yang masih bisa dibedakan — sekitar1e-07untukfloat32dan2e-16untukfloat64. Selisih tujuh tingkat besaran inilah ukuran presisi yang kita taruhkan.
| Tipe | Itemsize | Jangkauan inti | Khas untuk |
|---|---|---|---|
int8 / uint8 | 1 byte | -128..127 / 0..255 | label kelas, piksel |
int32 / uint32 | 4 byte | ±2,1 miliar | ID, jumlah baris menengah |
int64 | 8 byte | ±9,2 x 10^18 | indeks bawaan NumPy |
float32 | 4 byte | presisi ~7 digit | fitur machine learning, grafis |
float64 | 8 byte | presisi ~16 digit | perhitungan ilmiah default |
Matematika Memori per Juta Elemen #
Dengan itemsize di tangan, kebutuhan memori bisa dihitung sebelum data dibuat. Baris berikut mengalokasikan satu juta elemen pada lima dtype dan melaporkan nbytes:
import numpy as np
n = 1_000_000
for nama in ("float64", "float32", "int64", "int32", "uint8"):
a = np.zeros(n, dtype=nama)
print(f"{nama:8s} -> {a.nbytes:>9,} byte")Output yang Dihasilkan:
float64 -> 8,000,000 byte
float32 -> 4,000,000 byte
int64 -> 8,000,000 byte
int32 -> 4,000,000 byte
uint8 -> 1,000,000 byte- Baris 4-5: loop mencoba lima dtype pada jumlah elemen yang sama, sehingga satu-satunya variabel adalah
itemsize. - Baris 6 (
a.nbytes): hasilnya selalun x itemsize: delapan juta untuk tipe 8 byte, empat juta untuk 4 byte, dan satu juta untukuint8.
Skalanya berlaku linear: dataset seratus juta elemen float64 memakai 800 MB, sementara float32 cukup 400 MB — selisih yang menentukan apakah data muat di RAM mesin kerja.
uint8 untuk Data 0-255 #
Banyak data nyata yang jangkauannya alami 0-255: intensitas piksel grayscale, label kelas, nilai kuesioner. Menyimpannya sebagai float64 berarti memakai delapan kali kebutuhan sebenarnya:
import numpy as np
piksel = np.array([200, 150, 0, 255, 128], dtype=np.uint8)
print("dtype uint8 :", piksel.nbytes, "byte")
sebagai_float = piksel.astype(np.float64)
print("dtype float64:", sebagai_float.nbytes, "byte")Output yang Dihasilkan:
dtype uint8 : 5 byte
dtype float64: 40 byte- Baris 3 (
dtype=np.uint8): lima nilai muat persis di jangkauan 0-255, maka 5 byte sudah cukup. - Baris 5 (
astype): konversi kefloat64menaikkan konsumsi menjadi 40 byte tanpa menambah informasi sedikit pun.
Pola ini penting saat memuat gambar: citra 4000x3000 grayscale memakai 12 MB sebagai uint8 tetapi 96 MB sebagai float64 — perbandingan lengkapnya ada pada Chapter NumPy untuk Pemrosesan Gambar.
Kapan float32 Cukup #
Aturan singkatnya: float32 cukup bila nilai berada pada rentang wajar dan hasil tidak membutuhkan lebih dari ±7 digit signifikan. Kelemahannya paling terlihat saat menjumlahkan angka kecil ke akumulasi yang besar:
import numpy as np
x32 = np.array([1e8, 1, 1], dtype=np.float32)
x64 = np.array([1e8, 1, 1], dtype=np.float64)
print("float32:", x32.sum())
print("float64:", x64.sum())Output yang Dihasilkan:
float32: 100000000.0
float64: 100000002.0Cara membacanya:
- Baris 3-4: data yang sama disimpan dalam dua presisi; angka 100 juta masih dalam jangkauan keduanya.
- Baris 5-6: pada
float32, jarak antar nilai float di sekitar 100 juta sudah sekitar 8, sehingga tambahan1dan1tenggelam dan totalnya tidak berubah.float64menghasilkan100000002.0dengan benar.
Pedoman pilihan cepat:
- Label kelas dan piksel:
uint8atauint32— hemat dan presisi penuh. - Fitur machine learning berskala besar:
float32— pustaka seperti scikit-learn dan framework deep learning terbiasa dengannya. - Perhitungan ilmiah, uang, akumulasi panjang:
float64, atau bahkan tipe bulat untuk uang. - Ragu antara dua tipe: hitung selisih
nbytes, lalu uji akurasi hasil pada sampel data sebelum memutuskan.