Number dan Math JavaScript: Mengolah Nilai Angka

JavaScript cuma punya satu tipe angka untuk semuanya — bilangan bulat maupun desimal. Pelajari cara kerja angka yang sebenarnya, jebakan floating-point yang bikin semua orang kaget, serta perkakas Number dan Math untuk memformat, membulatkan, dan menghitung.

Diterbitkan 30 Juli 202612 menit bacaOleh ACY Partner Indonesia
Number dan Math JavaScript — menghitung dan memformat nilai angka
300 × 250Slot Iklan TersediaPasang iklan Anda di sini

Hampir setiap program pasti menghitung sesuatu di suatu tempat: total keranjang, persentase, harga plus pajak, atau memilih sesuatu secara acak dari sebuah daftar. JavaScript menangani semua itu cuma dengan satu tipe angka — dan keputusan tunggal inilah yang menentukan bagaimana angka berperilaku, termasuk satu keanehan yang bikin hampir semua orang bengong saat pertama kali melihatnya. Di artikel ini kamu bakal paham cara kerja angka di balik layar, jebakan floating-point dan cara menghindarinya, serta perkakas bawaan Number dan Math yang bakal sering banget kamu pakai.

Kamu sudah sempat kenalan dengan angka secara singkat di artikel tipe data. Sekarang kita gali lebih dalam sampai bug yang berhubungan dengan angka nggak lagi terasa misterius.

Satu tipe angka untuk semuanya

Kebanyakan bahasa pemrograman memecah angka ke beberapa tipe terpisah — integer, float, double, dan seterusnya. JavaScript memilih jalan yang lebih simpel: cuma ada satu tipe, namanya number, dan tipe itu mencakup bilangan bulat maupun desimal sekaligus.

const umur = 28;          // bilangan bulat
const harga = 19.99;      // desimal
const negatif = -7;       // angka negatif juga oke
const suhu = -3.5;

Kamu nggak perlu mendeklarasikan tipe “integer” atau “float” terpisah — tinggal tulis nilainya saja. Di balik layar, setiap angka di JavaScript disimpan sebagai nilai floating-point 64-bit (formatnya IEEE 754 “double”, kalau suatu saat kamu mau menelusurinya). Praktis memang, tapi inilah juga akar dari keanehan paling terkenal di bahasa ini, yang sebentar lagi kita bahas.

Kamu juga bisa menulis angka dengan beberapa notasi lain kalau memang lebih pas:

const besar = 1_000_000;    // garis bawah sebagai pemisah digit (cuma biar enak dibaca)
const hex = 0xff;           // heksadesimal → 255
const biner = 0b1010;       // biner → 10
const oktal = 0o17;         // oktal → 15
const ilmiah = 1.5e6;       // notasi ilmiah → 1500000

Garis bawahnya murni soal tampilan — JavaScript mengabaikannya, jadi 1_000_000 dan 1000000 itu angka yang sama persis. Fungsinya cuma bikin angka panjang lebih gampang dibaca.

Jebakan floating-point

Nah, yang ini selalu bikin pemula tersandung. Coba jalankan ini:

console.log(0.1 + 0.2);   // 0.30000000000000004  (!)
console.log(0.1 + 0.2 === 0.3);   // false

Itu bukan bug JavaScript — hal yang sama terjadi di hampir semua bahasa yang memakai standar floating-point serupa (Python, Java, C, dan lainnya). Penyebabnya: komputer menyimpan angka dalam bentuk biner (basis 2), dan persis seperti 1/3 yang nggak bisa ditulis pas dalam bentuk desimal (0.3333…), nilai 0.1 juga nggak bisa direpresentasikan secara persis dalam biner. Galat pembulatan yang kecil itulah yang bocor di ujung deretan desimal.

Jangan pernah bandingkan desimal langsung pakai ===

Karena pembulatan floating-point, 0.1 + 0.2 === 0.3 itu hasilnya false. Jangan membandingkan hasil desimal pakai === sambil berharap cocok persis. Kalau kamu butuh mengecek apakah dua desimal “cukup sama”, bandingkan selisihnya dengan toleransi yang sangat kecil:

const a = 0.1 + 0.2;
const b = 0.3;
console.log(Math.abs(a - b) < Number.EPSILON);   // true

Number.EPSILON adalah jarak terkecil yang masih berarti antara dua angka yang bisa dibedakan JavaScript — toleransi yang sudah jadi pas buat situasi seperti ini.

Hal ini paling krusial saat berurusan dengan uang. Menyimpan harga sebagai desimal floating-point lalu menjumlahkannya bisa pelan-pelan menumpuk galat pembulatan. Trik yang umum dipakai para profesional adalah bekerja dalam satuan terkecil — simpan nilai sebagai jumlah sen yang utuh (integer), bukan rupiah berkoma, lalu bagi 100 hanya saat menampilkannya. Bilangan bulat nggak kena masalah pembulatan yang sama.

// Daripada pakai rupiah berdesimal:
const total = 19.99 + 5.01;   // berisiko menyisakan ekor pembulatan

// Bekerja dalam sen (integer), baru dibagi di akhir:
const totalSen = 1999 + 501;          // 2500
const tampilan = (totalSen / 100).toFixed(2);   // "25.00"

Method Number yang berguna

Tipe number dibekali sejumlah method praktis untuk memformat dan memeriksa nilai. Dua yang paling sering kamu pakai adalah toFixed dan toString.

toFixed — kunci jumlah desimal

toFixed(n) membulatkan angka ke n angka di belakang koma dan mengembalikannya dalam bentuk string — pas banget buat menampilkan harga dan persentase:

const harga = 19.9;
console.log(harga.toFixed(2));    // "19.90"  (berupa string)

const pi = 3.14159;
console.log(pi.toFixed(2));       // "3.14"
console.log((1234.5678).toFixed(0));  // "1235"  (dibulatkan)

toFixed mengembalikan string, bukan number

Yang ini sering bikin orang keliru: (19.9).toFixed(2) memberimu string "19.90", bukan angka 19.9. Untuk keperluan menampilkan, biasanya itu justru yang kamu mau — angka nolnya tetap dipertahankan, jadi harga muncul sebagai 19.90, bukan 19.9. Tapi kalau kamu coba menghitung dengan hasilnya, JavaScript bakal menganggap + sebagai penyambungan string: "19.90" + 1 jadi "19.901", bukan 20.9. Format untuk tampilan setelah perhitunganmu selesai, jangan sebelumnya.

toString — ubah ke basis lain

toString() mengubah angka jadi string, dan kamu bisa memberinya basis (radix) untuk mengonversi antar sistem bilangan:

const n = 255;
console.log(n.toString());     // "255"  (basis 10, default-nya)
console.log(n.toString(16));   // "ff"   (heksadesimal)
console.log(n.toString(2));    // "11111111"  (biner)

Ini benar-benar berguna — mengubah angka ke basis 16 itu persis cara kamu menyusun kode warna heksadesimal dari nilai RGB, misalnya.

toLocaleString — format buat dibaca manusia

toLocaleString() memformat angka sesuai kebiasaan pembaca di wilayah tertentu, lengkap dengan pemisah yang tepat:

const jumlah = 1234567.89;

console.log(jumlah.toLocaleString("en-US"));   // "1,234,567.89"
console.log(jumlah.toLocaleString("id-ID"));   // "1.234.567,89"

// Lebih mantap lagi — format langsung sebagai mata uang:
console.log(jumlah.toLocaleString("id-ID", {
  style: "currency",
  currency: "IDR",
}));   // "Rp1.234.567,89"

Inilah alat yang tepat untuk menampilkan uang dan angka besar ke pengguna. Pemisah ribuan, koma vs titik untuk desimal, sampai simbol mata uang semuanya diurus otomatis berdasarkan locale — jauh lebih rapi ketimbang menyisipkan koma satu per satu secara manual.

Memeriksa angka: NaN dan Infinity

Angka punya dua nilai khusus yang perlu kamu kenal, karena keduanya muncul tepat saat perhitungan melenceng.

NaN — Bukan Angka

NaN artinya “Not a Number” alias bukan angka. Kamu mendapatkannya saat sebuah operasi yang seharusnya menghasilkan angka nggak bisa menghasilkan nilai numerik yang masuk akal:

console.log("halo" * 2);    // NaN
console.log(Number("abc")); // NaN
console.log(0 / 0);         // NaN

NaN punya sifat yang terkenal aneh: dia nggak sama dengan apa pun, bahkan dengan dirinya sendiri.

console.log(NaN === NaN);   // false  (!)

Jadi kamu nggak bisa mengeceknya pakai ===. Sebagai gantinya, pakai Number.isNaN():

const hasil = Number("abc");   // NaN
console.log(Number.isNaN(hasil));   // true

Pakai Number.isNaN, bukan isNaN global yang lama

Ada fungsi global lama bernama isNaN() (tanpa awalan Number.). Hindari yang ini — dia lebih dulu mencoba mengonversi argumennya jadi angka, sehingga isNaN("halo") mengembalikan true padahal string itu memang dari awal bukan angka. Number.isNaN() nggak melakukan konversi apa pun: dia hanya mengembalikan true untuk nilai yang benar-benar berupa NaN. Pakai Number.isNaN() dan kamu terhindar dari satu kelompok bug yang halus.

Infinity

Pembagian dengan nol nggak bikin JavaScript crash — hasilnya malah Infinity (atau -Infinity):

console.log(1 / 0);     // Infinity
console.log(-1 / 0);    // -Infinity
console.log(1 / 0 === Infinity);   // true

Untuk memastikan sebuah nilai benar-benar angka yang bisa dipakai — bukan NaN, bukan Infinity — pakai Number.isFinite():

console.log(Number.isFinite(42));         // true
console.log(Number.isFinite(Infinity));   // false
console.log(Number.isFinite(NaN));        // false

Ini penjaga yang bagus sebelum kamu mempercayai hasil sebuah perhitungan atau nilai hasil parsing.

Mengubah string jadi angka

Data dari form, URL, dan API sering datang dalam bentuk teks — "42", bukan 42. Kamu bakal terus-menerus perlu mengonversinya. Ada tiga cara umum, dan ketiganya berperilaku berbeda.

// 1. Number() — ketat, mengonversi seluruh string
console.log(Number("42"));      // 42
console.log(Number("42px"));    // NaN  ("px"-nya merusak)
console.log(Number("3.14"));    // 3.14

// 2. parseInt() — membaca integer dari DEPAN, berhenti di karakter aneh
console.log(parseInt("42px"));  // 42   (mengabaikan "px")
console.log(parseInt("3.14"));  // 3    (berhenti di titik)

// 3. parseFloat() — mirip parseInt tapi mempertahankan desimal
console.log(parseFloat("3.14")); // 3.14
console.log(parseFloat("3.14m"));// 3.14 (mengabaikan "m")

Perbedaannya penting. Number() itu semua-atau-tidak: seluruh string harus tampak seperti angka, kalau tidak hasilnya NaN. parseInt() dan parseFloat() lebih toleran — keduanya membaca sebanyak mungkin angka dari awal lalu diam-diam berhenti di karakter pertama yang nggak cocok. Itu persis yang kamu mau untuk hal seperti "42px" (yang kamu maksud 42), dan persis yang nggak kamu mau saat sebenarnya kamu ingin menangkap input yang salah.

Selalu beri radix pada parseInt

Biasakan memberi parseInt argumen kedua — basisnya — seperti parseInt("42", 10). Tanpa itu, input tertentu (dulu, string yang diawali 0) bisa diartikan dalam basis yang nggak kamu duga. Mesin modern memang umumnya memakai basis 10 secara default, tapi menulis parseInt(value, 10) membuat maksudmu jelas dan menghilangkan keraguan. Cuma menambah empat karakter, tapi membuang satu kelompok kejutan yang nggak perlu.

Ada jalan pintas yang sering kamu lihat di kode beneran: operator + unary mengubah string jadi angka, sama seperti Number().

const teks = "100";
const angka = +teks;      // 100, dalam bentuk angka
console.log(angka + 5);   // 105

Objek Math

Untuk apa pun yang melampaui aritmetika dasar, JavaScript menyediakan objek bawaan Math — kumpulan konstanta dan fungsi matematika. Kamu nggak perlu membuatnya; dia selalu ada. Kamu memanggil method-nya langsung dari Math.

Pembulatan

Method Math yang paling sering dipakai membulatkan angka dengan cara yang berbeda-beda:

console.log(Math.round(4.5));   // 5   (integer terdekat)
console.log(Math.round(4.4));   // 4
console.log(Math.ceil(4.1));    // 5   (selalu membulatkan KE ATAS)
console.log(Math.floor(4.9));   // 4   (selalu membulatkan KE BAWAH)
console.log(Math.trunc(4.9));   // 4   (cuma membuang desimalnya)
console.log(Math.trunc(-4.9));  // -4  (menuju nol)

Perlu kamu bedakan dengan jelas: round ke yang terdekat, ceil selalu ke atas, floor selalu ke bawah, dan trunc cukup memotong bagian desimal tanpa membulatkan sama sekali. Untuk angka negatif, floor dan trunc beda hasil — Math.floor(-4.9) itu -5, sedangkan Math.trunc(-4.9) itu -4.

Perhitungan yang umum

Sejumlah method Math muncul berulang-ulang:

console.log(Math.abs(-7));        // 7    (nilai mutlak)
console.log(Math.pow(2, 10));     // 1024 (2 pangkat 10)
console.log(2 ** 10);             // 1024 (operator ** — sama saja)
console.log(Math.sqrt(144));      // 12   (akar kuadrat)
console.log(Math.max(3, 9, 1));   // 9    (terbesar)
console.log(Math.min(3, 9, 1));   // 1    (terkecil)

Operator pangkat ** melakukan tugas yang sama dengan Math.pow dan terbaca sedikit lebih bersih, jadi sering kali kamu bakal lebih memilihnya. Lalu Math.max/Math.min menerima argumen berapa pun jumlahnya — praktis untuk mencari skor tertinggi atau harga terendah dari sekumpulan nilai.

Cari nilai maksimum array pakai operator spread

Math.max menerima daftar angka, bukan array. Kalau kamu sudah punya array, sebarkan isinya pakai ...:

const skor = [82, 91, 67, 100, 73];
console.log(Math.max(...skor));   // 100
console.log(Math.min(...skor));   // 67

... “menyebarkan” isi array jadi argumen-argumen terpisah, seolah-olah kamu mengetik Math.max(82, 91, 67, 100, 73). Ini cara standar untuk mendapatkan nilai terbesar atau terkecil dari sebuah array.

Konstanta Math

Math juga menyimpan beberapa konstanta yang berguna:

console.log(Math.PI);   // 3.141592653589793
console.log(Math.E);    // 2.718281828459045

// Luas lingkaran dengan jari-jari 5:
const jari = 5;
const luas = Math.PI * jari ** 2;
console.log(luas.toFixed(2));   // "78.54"

Angka acak

Math.random() mengembalikan desimal acak antara 0 (termasuk) dan 1 (tidak termasuk) — jadi nilainya di suatu titik dari 0 sampai mendekati, tapi nggak pernah menyentuh, 1:

console.log(Math.random());   // mis. 0.7263… (beda tiap kali)

Kalau berdiri sendiri, itu jarang jadi yang kamu butuhkan. Yang umum dibutuhkan adalah integer acak dalam rentang tertentu, dan ada resep standar untuk itu:

// Integer acak dari min sampai max (keduanya termasuk):
function angkaAcak(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

console.log(angkaAcak(1, 6));    // lemparan dadu: 1–6
console.log(angkaAcak(1, 100));  // 1–100

Baca dari dalam ke luar: Math.random() memberi pecahan, perkalian memperbesarnya seukuran rentangmu, Math.floor memangkasnya jadi bilangan bulat, lalu penambahan min menggesernya agar mulai di titik yang benar. Memilih item acak dari sebuah array pakai ide yang sama:

const warna = ["merah", "hijau", "biru"];
const pilihan = warna[Math.floor(Math.random() * warna.length)];
console.log(pilihan);   // salah satu dari tiga, secara acak

Math.random tidak aman untuk keamanan

Math.random() oke buat game, pengacakan, atau memilih tip acak untuk ditampilkan — apa pun yang sekadar “enak kalau tak tertebak”. Tapi dia bukan sumber acak yang aman secara kriptografis, jadi jangan pernah memakainya untuk membuat password, token sesi, atau apa pun yang sensitif secara keamanan. Untuk itu, browser menyediakan crypto.getRandomValues(), yang memang dirancang untuk benar-benar tak tertebak. Sesuaikan alat dengan taruhannya.

Saat integer biasa nggak cukup: BigInt

Angka biasa aman dan presisi hanya sampai batas tertentu — Number.MAX_SAFE_INTEGER, yaitu 9007199254740991 (sedikit di atas 9 kuadriliun). Lewat dari titik itu, bilangan bulat bisa diam-diam kehilangan presisi:

console.log(Number.MAX_SAFE_INTEGER);   // 9007199254740991
console.log(9007199254740991 + 1);      // 9007199254740992  (oke)
console.log(9007199254740991 + 2);      // 9007199254740992  (salah! harusnya ...993)

Untuk kasus langka yang benar-benar butuh bilangan bulat raksasa — ID database yang besar, sebagian pekerjaan finansial atau ilmiah — JavaScript punya BigInt. Cara membuatnya: tambahkan n di akhir literal integer:

const raksasa = 9007199254740991n;
console.log(raksasa + 2n);   // 9007199254740993n  (benar!)

Catatannya: kamu nggak bisa mencampur BigInt dengan angka biasa dalam satu operasi (10n + 5 bakal melempar error — kamu harus menulis 10n + 5n), dan BigInt nggak bisa menampung desimal. Untuk pekerjaan sehari-hari, cukup pakai angka biasa; gunakan BigInt hanya saat kamu benar-benar menabrak batas safe-integer.

Contoh realistis

Coba kita rangkai beberapa hal tadi jadi sesuatu yang mungkin betulan kamu tulis — ringkasan pesanan kecil:

const pesanan = {
  pelanggan: "John Doe",
  items: [
    { nama: "Keyboard", harga: 250000, jumlah: 1 },
    { nama: "Mouse", harga: 120000, jumlah: 2 },
  ],
};

// Jumlahkan harga × jumlah dari tiap item
let subtotal = 0;
for (const item of pesanan.items) {
  subtotal += item.harga * item.jumlah;
}

const tarifPajak = 0.11;               // pajak 11%
const pajak = subtotal * tarifPajak;
const total = subtotal + pajak;

console.log("Subtotal:", subtotal.toLocaleString("id-ID"));   // 490.000
console.log("Pajak:", Math.round(pajak).toLocaleString("id-ID")); // 53.900
console.log("Total:", Math.round(total).toLocaleString("id-ID")); // 543.900

Inilah angka yang benar-benar bekerja: ada perulangan untuk menjumlahkan (for...of dari artikel perulangan), aritmetika untuk pajak, Math.round untuk merapikan hasilnya, dan toLocaleString untuk menyajikannya sesuai cara orang membacanya.

Penutup

Sekarang kamu sudah pegang kendali yang kokoh atas cara angka berperilaku di JavaScript beserta perkakasnya:

  • JavaScript punya satu tipe angka untuk bilangan bulat maupun desimal. Di balik layar bentuknya floating-point 64-bit — praktis, tapi jadi sumber satu keanehan klasik.
  • Matematika desimal nggak persis (0.1 + 0.2 !== 0.3). Jangan bandingkan desimal pakai ===; untuk uang, bekerjalah dalam satuan terkecil (sen) sebagai integer.
  • Method Number memformat dan mengonversi: toFixed(n) untuk desimal tetap (mengembalikan string), toString(radix) untuk basis lain, toLocaleString() untuk format yang ramah dibaca dan format mata uang.
  • NaN artinya “bukan angka” dan nggak sama dengan apa pun, bahkan dirinya sendiri — cek pakai Number.isNaN(). Pembagian dengan nol menghasilkan Infinity — jaga hasil yang valid dengan Number.isFinite().
  • Konversi string pakai Number() (ketat), parseInt(str, 10), atau parseFloat() (longgar). Selalu beri radix pada parseInt.
  • Objek Math menangani sisanya: round/ceil/floor/trunc untuk pembulatan, abs/sqrt/max/min/** untuk perhitungan, dan Math.random() untuk keacakan (bukan untuk keamanan).
  • Untuk bilangan bulat melebihi Number.MAX_SAFE_INTEGER, gunakan BigInt (123n).

Angka dan teks adalah dua bahan mentah yang menyusun hampir semua program. Sekarang kamu sudah menguasai sisi numeriknya, dan di dasar-dasar string dan tipe data kamu sudah menyentuh sisi teksnya. Berikutnya, kita bahas tanggal dan waktu — yang ternyata juga disimpan sebagai angka, jadi semua yang baru saja kamu pelajari di sini langsung kepakai.

Tag:javascriptfrontendnumbermathmenengah
728 × 90Slot Iklan TersediaPasang iklan Anda di sini

Artikel Terkait

Lihat Semua Artikel

Artikel yang Mungkin Kamu Suka

Apa Itu Framework Frontend? — chip kode dengan tag komponen
Frontend / Dasar

Apa Itu Framework Frontend?

Penjelasan ramah untuk pemula tentang apa itu framework frontend, kenapa mereka ada, masalah apa yang mereka selesaikan dibanding JavaScript biasa, dan kapan kamu memang sebaiknya memakainya.

20 Sep 20268 menit baca
Sampul fundamentals frontend bertuliskan Apa Itu Frontend dan HTML + CSS + JS
Frontend / Dasar

Apa Itu Frontend Development?

Panduan ramah pemula tentang frontend development: bagian website yang kamu lihat dan klik secara langsung. Pahami cara kerja HTML, CSS, dan JavaScript, serta bedanya frontend dengan backend.

20 Sep 20268 menit baca
Ilustrasi sampul untuk Apa yang Dikerjakan Frontend Developer
Frontend / Dasar

Apa yang Dikerjakan Frontend Developer: Panduan untuk Pemula

Penjelasan ramah pemula tentang apa yang sebenarnya dikerjakan frontend developer setiap hari: mengubah desain jadi antarmuka yang berfungsi, membangun UI yang bisa dipakai ulang, sampai urusan responsif, aksesibilitas, dan kecepatan.

20 Sep 20269 menit baca
Kartu judul bertuliskan Styling dan Interaktivitas di atas latar biru gelap ACY Partner
Frontend / Dasar

Cara Kerja Styling dan Interaktivitas

Penjelasan ramah pemula soal bagaimana CSS menyulap HTML polos jadi tampilan rapi, dan bagaimana JavaScript menambahkan perilaku — pola berpikir struktur, gaya, perilaku saat membangun halaman web.

20 Sep 20268 menit baca
Tiga lapisan front-end menyatu di satu halaman web
Frontend / Dasar

Cara HTML, CSS, dan JavaScript Bekerja Bersama

Panduan praktis untuk pemula: bikin satu tombol kecil, beri struktur dengan HTML, tampilan dengan CSS, dan perilaku dengan JavaScript, lalu lihat ketiga lapisan ini bekerja sama di halaman nyata.

20 Sep 20268 menit baca
Sampul ikhtisar praktik terbaik frontend
Frontend / Dasar

Ikhtisar Praktik Terbaik Frontend

Peta ringkas tentang apa itu frontend yang baik — HTML bermakna, CSS rapi, JavaScript secukupnya, desain responsif, performa, dan progressive enhancement, lengkap dengan arahan untuk mendalaminya.

20 Sep 20268 menit baca