Pembulatan np.round yang dibahas sebelumnya mencari tetangga terdekat. Kebutuhan lain justru menuntut arah tetap: alokasi slot memori selalu ke atas, diskon kupon selalu ke bawah, dan tagihan pengiriman selalu naik ke kelipatan berat berikutnya. Untuk itu NumPy menyediakan np.floor dan np.ceil, ditambah np.modf yang memisahkan bagian pecahan dari bagian bulat sebuah nilai.

floor: Selalu ke Bawah, ceil: Selalu ke Atas #

np.floor membulatkan menuju negatif tak hingga (bawah), sedangkan np.ceil membulatkan menuju positif tak hingga (atas). Arah ini tidak berubah meskipun nilai yang diproses negatif:

python
import numpy as np

x = np.array([2.3, -2.3, 5.0, -0.1])
print(np.floor(x))
print(np.ceil(x))
print(np.fix(x))

Output yang Dihasilkan:

text
[ 2. -3.  5. -1.]
[ 3. -2.  5. -0.]
[ 2. -2.  5. -0.]

Baris np.fix sengaja disertakan sebagai pembanding karena ketiga fungsi ini paling mudah tertukar pada bilangan negatif. Tabel berikut merangkumnya:

Nilaifloorceilfixround (banker’s)
2.32.03.02.02.0
-2.3-3.0-2.0-2.0-2.0
5.05.05.05.05.0
-0.1-1.0-0.0-0.0-0.0

Dua hal layak dicatat dari tabel di atas. Pertama, floor(-2.3) menghasilkan -3.0 — lebih kecil dari input — sementara ceil(-2.3) menghasilkan -2.0. Kedua, nilai negatif mendekati nol ditampilkan sebagai -0.0; nilai ini bernilai sama dengan 0.0 dalam perbandingan, hanya representasi binernya yang berbeda tanda.

modf: Memisahkan Pecahan dan Bagian Bulat #

np.modf memecah setiap nilai menjadi dua array: bagian pecahan dan bagian bulat. Urutan hasilnya sering mengejutkan pemula — pecahan keluar lebih dulu, baru bagian bulat:

python
import numpy as np

x = np.array([3.75, -2.3, 5.0])
pecahan, bulat = np.modf(x)
print(pecahan)
print(bulat)

Output yang Dihasilkan:

text
[ 0.75 -0.3   0.  ]
[ 3. -2.  5.]

Mari kita bedah:

  1. Baris 3 (np.modf(x)): fungsi mengembalikan tuple berisi dua array, sehingga baris 4 melakukan tuple unpacking ke dua variabel sekaligus.
  2. Variabel pecahan: berisi bagian di belakang koma dengan tanda yang sama seperti input; perhatikan -2.3 menghasilkan -0.3, bukan 0.3.
  3. Variabel bulat: berisi hasil np.fix, yaitu pemotongan menuju nol, sehingga -2.3 menjadi -2.0.

Karena urutannya (fractional, integral), kesalahan umum pemula adalah menulis bulat, pecahan = np.modf(x). Program tetap berjalan tanpa error, tetapi kedua variabel saling tertukar.

Pasangan np.floor dan np.ceil juga menjadi fondasi pola umum lain: menghitung banyaknya kelompok penuh yang dibutuhkan. Untuk membagi 1.000 data ke batch berukuran 128, banyaknya batch adalah np.ceil(1000 / 128) = 8.0, karena 7 batch hanya memuat 896 data. Konversi ke integer dengan .astype(np.int64) dilakukan setelah pembulatan, bukan sebelumnya — memotong ke integer terlebih dahulu (int(1000/128) = 7) akan membuang sisa 104 data dari perhitungan.

Studi Kasus: Biaya Pengiriman dengan ceil #

Pengiriman barang umumnya ditagih per kilogram penuh: berat 1.2 kg dan 1.9 kg sama-sama dihitung 2 kg. Aturan “naik ke kelipatan berikutnya” ini persis pekerjaan np.ceil:

python
import numpy as np

berat_kg = np.array([1.2, 3.5, 0.4, 2.0])
berat_tagih = np.ceil(berat_kg)
tarif_per_kg = 8000
biaya = berat_tagih * tarif_per_kg
print(berat_tagih)
print(biaya)

Output yang Dihasilkan:

text
[2. 4. 1. 2.]
[16000. 32000.  8000. 16000.]

np.ceil mengubah setiap berat ke kilogram penuh berikutnya, lalu perkalian dengan tarif per kilogram menghasilkan biaya untuk keempat kiriman sekaligus. Pola yang sama berlaku untuk alokasi halaman cetak, penentuan jumlah kontainer, atau pembulatan harga ke atas sesuai kebijakan toko.