- 1 1. Pengantar
- 2 2. Apa Itu BigDecimal?
- 3 3. Penggunaan Dasar BigDecimal
- 4 4. Penggunaan Lanjutan BigDecimal
- 5 5. Kesalahan Umum dan Cara Memperbaikinya
- 6 6. Contoh Penggunaan Praktis
- 7 7. Ringkasan
- 8 8. FAQ: Pertanyaan yang Sering Diajukan tentang BigDecimal
- 8.1 Q1. Mengapa saya harus menggunakan BigDecimal alih-alih float atau double?
- 8.2 Q2. Apa cara paling aman untuk membuat instance BigDecimal?
- 8.3 Q3. Mengapa divide() melempar pengecualian?
- 8.4 Q4. Apa perbedaan antara compareTo() dan equals()?
- 8.5 Q5. Bagaimana cara melakukan pembulatan?
- 8.6 Q7. Bagaimana cara menangani input null/kosong dengan aman?
1. Pengantar
Masalah Presisi dalam Perhitungan Numerik di Java
Dalam pemrograman Java, perhitungan numerik dilakukan secara harian. Misalnya, menghitung harga produk, menentukan pajak atau bunga — operasi ini diperlukan dalam banyak aplikasi. Namun, ketika perhitungan seperti itu dilakukan menggunakan tipe titik mengambang seperti float atau double, kesalahan tak terduga mungkin terjadi.
Ini terjadi karena float dan double merepresentasikan nilai sebagai aproksimasi biner. Nilai seperti “0.1” atau “0.2,” yang dapat diekspresikan secara akurat dalam desimal, tidak dapat direpresentasikan secara tepat dalam biner — dan akibatnya, kesalahan kecil menumpuk.
BigDecimal Sangat Penting untuk Perhitungan Moneter atau Presisi
Kesalahan seperti itu bisa kritis di bidang seperti perhitungan moneter dan perhitungan ilmiah/teknik presisi. Misalnya, dalam perhitungan tagihan, bahkan perbedaan 1 yen bisa menyebabkan masalah kredibilitas.
Di sinilah kelas BigDecimal Java unggul. BigDecimal dapat menangani angka desimal dengan presisi arbitrer dan dengan menggunakannya sebagai pengganti float atau double, perhitungan numerik dapat dilakukan tanpa kesalahan.
Apa yang Akan Anda Dapatkan Dari Artikel Ini
Dalam artikel ini, kami akan menjelaskan dasar-dasar penggunaan BigDecimal di Java, teknik lanjutan, serta kesalahan umum dan peringatan secara sistematis.
Ini berguna bagi mereka yang ingin menangani perhitungan moneter secara akurat di Java atau sedang mempertimbangkan untuk mengadopsi BigDecimal dalam proyek mereka.
2. Apa Itu BigDecimal?
Gambaran Umum BigDecimal
BigDecimal adalah kelas di Java yang memungkinkan aritmatika desimal presisi tinggi. Ia termasuk dalam paket java.math dan dirancang khusus untuk perhitungan yang tidak toleran terhadap kesalahan seperti komputasi keuangan/akuntansi/pajak.
Dengan float dan double Java, nilai numerik disimpan sebagai aproksimasi biner — artinya desimal seperti “0.1” atau “0.2” tidak dapat direpresentasikan secara tepat, yang menjadi sumber kesalahan. Sebaliknya, BigDecimal menyimpan nilai sebagai representasi desimal berbasis string, sehingga menekan kesalahan pembulatan dan aproksimasi.
Penanganan Angka Presisi Arbitrer
Karakteristik terbesar dari BigDecimal adalah “presisi arbitrer.” Bagian integer dan desimal secara teori dapat menangani hampir tak terbatas digit, menghindari pembulatan atau kehilangan digit karena batasan digit.
Misalnya, angka besar berikut dapat ditangani secara akurat:
BigDecimal bigValue = new BigDecimal("12345678901234567890.12345678901234567890");
Dapat melakukan aritmatika sambil mempertahankan presisi seperti ini adalah kekuatan utama dari BigDecimal.
Kasus Penggunaan Utama
BigDecimal direkomendasikan dalam situasi seperti:
- Perhitungan moneter — bunga, komputasi tarif pajak di aplikasi keuangan
- Pemrosesan jumlah invoice / kutipan
- Komputasi ilmiah/teknik yang memerlukan presisi tinggi
- Proses di mana akumulasi jangka panjang menyebabkan penumpukan kesalahan
Misalnya, dalam sistem akuntansi dan perhitungan gaji — di mana perbedaan 1 yen bisa menyebabkan kerugian besar atau sengketa — presisi BigDecimal sangat penting.
3. Penggunaan Dasar BigDecimal
Cara Membuat Instance BigDecimal
Tidak seperti literal numerik normal, BigDecimal secara umum harus dibangun dari string. Ini karena nilai yang dibuat dari double atau float mungkin sudah mengandung kesalahan aproksimasi biner. Direkomendasikan (bangun dari String):
BigDecimal value = new BigDecimal("0.1");
Hindari (bangun dari double):
BigDecimal value = new BigDecimal(0.1); // may contain error
Cara Melakukan Aritmatika
BigDecimal tidak dapat digunakan dengan operator aritmatika normal (+, -, *, /). Sebaliknya, metode khusus harus digunakan. Penjumlahan (add)
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("2.3");
BigDecimal result = a.add(b); // 12.8
Pengurangan (subtract)
BigDecimal result = a.subtract(b); // 8.2
Perkalian (multiply)
BigDecimal result = a.multiply(b); // 24.15
Pembagian (divide) dan Mode Pembulatan Pembagian memerlukan kehati-hatian. Jika tidak dapat dibagi secara merata, ArithmeticException akan terjadi kecuali mode pembulatan ditentukan.
BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); // 3.33
Di sini kami menentukan “2 tempat desimal” dan “pembulatan setengah ke atas.”
Pengaturan Skala dan Mode Pembulatan dengan setScale
setScale dapat digunakan untuk membulatkan ke jumlah digit yang ditentukan.
BigDecimal value = new Big BigDecimal("123.456789");
BigDecimal rounded = value.setScale(2, RoundingMode.HALF_UP); // 123.46
Nilai RoundingMode umum:
| Mode Name | Description |
|---|---|
HALF_UP | Round half up (standard rounding) |
HALF_DOWN | Round half down |
HALF_EVEN | Banker’s rounding |
UP | Always round up |
DOWN | Always round down |
BigDecimal Tidak Dapat Diubah
BigDecimal adalah immutable. Artinya — metode aritmatika (add, subtract, dll.) tidak memodifikasi nilai asli — mereka mengembalikan instance baru.
BigDecimal original = new BigDecimal("5.0");
BigDecimal result = original.add(new BigDecimal("1.0"));
System.out.println(original); // still 5.0
System.out.println(result); // 6.0
4. Penggunaan Lanjutan BigDecimal
Membandingkan Nilai: Perbedaan Antara compareTo dan equals
Di BigDecimal, ada dua cara untuk membandingkan nilai: compareTo() dan equals(), dan perilaku ini berbeda.
compareTo()membandingkan hanya nilai numerik (mengabaikan skala).equals()membandingkan termasuk skala (jumlah digit desimal).BigDecimal a = new BigDecimal("10.0"); BigDecimal b = new BigDecimal("10.00"); System.out.println(a.compareTo(b)); // 0 (values are equal) System.out.println(a.equals(b)); // false (scale differs)
Poin: Untuk pemeriksaan kesetaraan numerik — seperti kesetaraan moneter — compareTo() umumnya direkomendasikan.
Mengonversi Ke/Dari String
Dalam input pengguna dan impor file eksternal, konversi dengan tipe String umum. String → BigDecimal
BigDecimal value = new Big BigDecimal("1234.56");
BigDecimal → String
String str = value.toString(); // "1234.56"
Menggunakan valueOf Java juga memiliki BigDecimal.valueOf(double val), tetapi ini juga secara internal mengandung kesalahan double, sehingga membangun dari string masih lebih aman.
BigDecimal unsafe = BigDecimal.valueOf(0.1); // contains internal error
Presisi dan Aturan Pembulatan melalui MathContext
MathContext memungkinkan Anda mengontrol presisi dan mode pembulatan sekaligus — berguna saat menerapkan aturan umum di banyak operasi.
MathContext mc = new MathContext(4, RoundingMode.HALF_UP);
BigDecimal result = new BigDecimal("123.4567").round(mc); // 123.5
Juga dapat digunakan dalam aritmatika:
BigDecimal a = new BigDecimal("10.456");
BigDecimal b = new BigDecimal("2.1");
BigDecimal result = a.multiply(b, mc); // 4-digit precision
Pemeriksaan null dan Inisialisasi Aman
Formulir mungkin meneruskan nilai null atau kosong — kode penjaga adalah standar.
String input = ""; // empty
BigDecimal value = (input == null || input.isEmpty()) ? BigDecimal.ZERO : new BigDecimal(input);
Memeriksa Skala BigDecimal
Untuk mengetahui digit desimal, gunakan scale():
BigDecimal value = new BigDecimal("123.45");
System.out.println(value.scale()); // 3
5. Kesalahan Umum dan Cara Memperbaikinya
ArithmeticException: Ekspansi desimal yang tidak berakhir
Contoh Kesalahan:
BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("3");
BigDecimal result = a.divide(b); // exception
Ini adalah “1 ÷ 3” — karena menjadi desimal yang tidak berakhir, jika tidak ada mode pembulatan/skala yang diberikan, eksepsi akan dilempar. Perbaikan: tentukan skala + mode pembulatan
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); // OK (3.33)
Kesalahan Saat Membangun Langsung Dari double
Meneruskan double secara langsung mungkin sudah mengandung kesalahan biner — menghasilkan nilai tak terduga. Contoh Buruk:
BigDecimal val = new BigDecimal(0.1);
System.out.println(val); // 0.100000000000000005551115123...
Benar: Gunakan String
BigDecimal val = new BigDecimal("0.1"); // exact 0.1
Catatan: BigDecimal.valueOf(0.1) menggunakan Double.toString() secara internal, sehingga hampir sama dengan new BigDecimal("0.1") — tetapi string adalah yang paling aman 100 %.

Kesalahpahaman equals Karena Ketidaksesuaian Skala
Karena equals() membandingkan skala, ia dapat mengembalikan false meskipun nilai secara numerik sama.
BigDecimal a = new BigDecimal("10.0");
BigDecimal b = new BigDecimal("10.00");
System.out.println(a.equals(b)); // false
Solusi: gunakan compareTo() untuk kesetaraan numerik
System.out.println(a.compareTo(b)); // 0
Hasil Tak Terduga Karena Presisi Tidak Cukup
Jika menggunakan setScale tanpa menentukan mode pembulatan — pengecualian dapat terjadi.
Contoh Buruk:
BigDecimal value = new BigDecimal("1.2567");
BigDecimal rounded = value.setScale(2); // exception
Solusi:
BigDecimal rounded = value.setScale(2, RoundingMode.HALF_UP); // OK
NumberFormatException Ketika Nilai Input Tidak Valid
Jika teks tidak valid yang tidak dapat diurai sebagai angka diberikan (misalnya, input pengguna / bidang CSV), NumberFormatException akan terjadi.
Solusi: gunakan penanganan pengecualian
try {
BigDecimal value = new BigDecimal(userInput);
} catch (NumberFormatException e) {
// show error message or fallback logic
}
6. Contoh Penggunaan Praktis
Di sini kami memperkenalkan skenario dunia nyata yang menunjukkan bagaimana BigDecimal dapat digunakan dalam praktik. Terutama dalam perhitungan keuangan/akuntansi/pajak, pentingnya penanganan numerik yang akurat menjadi jelas.
Menangani Desimal dalam Perhitungan Harga (Pembulatan Pecahan)
Contoh: Menghitung harga termasuk pajak konsumsi 10 %
BigDecimal price = new BigDecimal("980"); // price w/o tax
BigDecimal taxRate = new BigDecimal("0.10");
BigDecimal tax = price.multiply(taxRate).setScale(0, RoundingMode.HALF_UP);
BigDecimal total = price.add(tax);
System.out.println("Tax: " + tax); // Tax: 98
System.out.println("Total: " + total); // Total: 1078
Poin:
- Hasil perhitungan pajak sering diproses sebagai bilangan bulat, menggunakan
setScale(0, RoundingMode.HALF_UP)untuk membulatkan. doublecenderung menghasilkan kesalahan —BigDecimaldisarankan.
Perhitungan Diskon (% OFF)
Contoh: Diskon 20 %
BigDecimal originalPrice = new BigDecimal("3500");
BigDecimal discountRate = new BigDecimal("0.20");
BigDecimal discount = originalPrice.multiply(discountRate).setScale(0, RoundingMode.HALF_UP);
BigDecimal discountedPrice = originalPrice.subtract(discount);
System.out.println("Discount: " + discount); // Discount: 700
System.out.println("After discount: " + discountedPrice); // 2800
Poin: Perhitungan diskon harga tidak boleh kehilangan presisi.
Perhitungan Harga Satuan × Kuantitas (Skenario Aplikasi Bisnis Umum)
Contoh: 298,5 yen × 7 barang
BigDecimal unitPrice = new BigDecimal("298.5");
BigDecimal quantity = new BigDecimal("7");
BigDecimal total = unitPrice.multiply(quantity).setScale(2, RoundingMode.HALF_UP);
System.out.println("Total: " + total); // 2089.50
Poin:
- Sesuaikan pembulatan untuk perkalian pecahan.
- Penting untuk sistem akuntansi / pemesanan.
Perhitungan Bunga Majemuk (Contoh Keuangan)
Contoh: Bunga tahunan 3 % × 5 tahun
BigDecimal principal = new BigDecimal("1000000"); // base: 1,000,000
BigDecimal rate = new BigDecimal("0.03");
int years = 5;
BigDecimal finalAmount = principal;
for (int i = 0; i < years; i++) {
finalAmount = finalAmount.multiply(rate.add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_UP);
}
System.out.println("After 5 years: " + finalAmount); // approx 1,159,274.41
Poin:
- Perhitungan berulang mengakumulasi kesalahan —
BigDecimalmenghindarinya.
Validasi & Konversi Input Pengguna
public static BigDecimal parseAmount(String input) {
try {
return new BigDecimal(input).setScale(2, RoundingMode.HALF_UP);
} catch (NumberFormatException e) {
return BigDecimal.ZERO; // treat invalid input as 0
}
}
Poin:
- Mengonversi string numerik yang diberikan pengguna dengan aman.
- Validasi + penanganan kesalahan meningkatkan ketahanan.
7. Ringkasan
Peran BigDecimal
Dalam pemrosesan numerik Java — terutama logika moneter atau yang memerlukan pres — kelas BigDecimal sangat penting. Kesalahan yang melekat pada float / double dapat dihindari secara signifikan dengan menggunakan BigDecimal.
Artikel ini membahas dasar-dasar, operasi aritmetika, perbandingan, pembulatan, penanganan kesalahan, dan contoh dunia nyata.
Poin Tinjauan Utama
BigDecimalmenangani desimal dengan presisi tak terbatas — ideal untuk uang dan perhitungan presisi- Inisialisasi sebaiknya menggunakan literal string, misalnya
new BigDecimal("0.1") - Gunakan
add(),subtract(),multiply(),divide(), dan selalu tentukan mode pembulatan saat melakukan pembagian - Gunakan
compareTo()untuk kesetaraan — pahami perbedaan denganequals() setScale()/MathContextmemungkinkan Anda mengontrol skala + pembulatan secara halus- Contoh kasus logika bisnis nyata meliputi uang, pajak, kuantitas × harga satuan, dll.
Bagi Mereka yang Akan Menggunakan BigDecimal
Meskipun “menangani angka di Java” tampak sederhana — masalah presisi / pembulatan / kesalahan numerik selalu ada di baliknya. BigDecimal adalah alat yang secara langsung mengatasi masalah tersebut — menguasainya memungkinkan Anda menulis kode yang lebih dapat diandalkan.
Pada awalnya Anda mungkin kesulitan dengan mode pembulatan — tetapi dengan penggunaan proyek nyata, hal itu menjadi alami.
Bab berikutnya adalah bagian FAQ yang merangkum pertanyaan umum tentang BigDecimal — berguna untuk tinjauan dan pencarian semantik spesifik.
8. FAQ: Pertanyaan yang Sering Diajukan tentang BigDecimal
Q1. Mengapa saya harus menggunakan BigDecimal alih-alih float atau double?
A1.
Karena float/double merepresentasikan angka sebagai aproksimasi biner — pecahan desimal tidak dapat direpresentasikan secara tepat. Hal ini menyebabkan hasil seperti “0.1 + 0.2 ≠ 0.3.”
BigDecimal mempertahankan nilai desimal secara tepat — ideal untuk uang atau logika yang memerlukan presisi tinggi.
Q2. Apa cara paling aman untuk membuat instance BigDecimal?
A2.
Selalu buat dari string.
Buruk (error):
new BigDecimal(0.1)
Benar:
new BigDecimal("0.1")
BigDecimal.valueOf(0.1) menggunakan Double.toString() secara internal, jadi hampir sama — tetapi string adalah yang paling aman.
Q3. Mengapa divide() melempar pengecualian?
A3.
Karena BigDecimal.divide() melempar ArithmeticException ketika hasilnya merupakan desimal yang tidak berakhir.
Solusi: tentukan skala + mode pembulatan
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP);
Q4. Apa perbedaan antara compareTo() dan equals()?
A4.
compareTo()memeriksa kesetaraan numerik (skala diabaikan)equals()memeriksa kesetaraan tepat termasuk skalanew BigDecimal("10.0").compareTo(new BigDecimal("10.00")); // → 0 new BigDecimal("10.0").equals(new BigDecimal("10.00")); // → false
Q5. Bagaimana cara melakukan pembulatan?
A5.
Gunakan setScale() dengan mode pembulatan yang eksplisit.
BigDecimal value = new BigDecimal("123.4567");
BigDecimal rounded = value.setScale(2, RoundingMode.HALF_UP); // 123.46
Mode pembulatan utama:
RoundingMode.HALF_UP(pembulatan setengah ke atas)RoundingMode.DOWN(pembulatan ke bawah)- `RoundingMode.UPpembulatan### Q6.akah saya memeriksa digit desimal (skala)?
A6.
Ya — gunakan scale().
BigDecimal val = new BigDecimal("123.45");
System.out.println(val.scale()); // → 3
Q7. Bagaimana cara menangani input null/kosong dengan aman?
A7.
Selalu sertakan pemeriksaan null + penanganan pengecualian.
public static BigDecimal parseSafe(String input) {
if (input == null || input.trim().isEmpty()) return BigDecimal.ZERO;
try {
return new BigDecimal(input.trim());
} catch (NumberFormatException e) {
return BigDecimal.ZERO;
}
}