- 1 1. Pendahuluan
- 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. Summary
- 8 8. FAQ: Frequently Asked Questions About BigDecimal
- 8.1 Q1. Why should I use BigDecimal instead of float or double?
- 8.2 Q2. What is the safest way to construct BigDecimal instances?
- 8.3 Q3. Why does divide() throw an exception?
- 8.4 Q4. What’s the difference between compareTo() and equals()?
- 8.5 Q5. How do I perform rounding?
- 8.6 Q6. Can I check decimal digits (scale)?
- 8.7 Q7. How should I handle null/empty input safely?
1. Pendahuluan
Masalah Presisi dalam Perhitungan Numerik di Java
Dalam pemrograman Java, perhitungan numerik dilakukan setiap hari. Misalnya, menghitung harga produk, menentukan pajak atau bunga — operasi‑operasi ini diperlukan dalam banyak aplikasi. Namun, ketika perhitungan tersebut dilakukan menggunakan tipe floating‑point seperti float atau double, kesalahan yang tidak terduga dapat muncul.
Hal 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‑kesalahan kecil menumpuk.
BigDecimal Penting untuk Perhitungan Moneter atau Presisi
Kesalahan‑kesalahan semacam itu dapat menjadi kritis dalam bidang seperti perhitungan moneter dan perhitungan ilmiah/rekayasa dengan presisi tinggi. Contohnya, dalam perhitungan tagihan, selisih 1 yen saja dapat menimbulkan masalah kredibilitas.
Di sinilah kelas BigDecimal Java bersinar. BigDecimal dapat menangani angka desimal dengan presisi sewenang‑wenang dan dengan menggunakannya menggantikan 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.
Hal ini berguna bagi mereka yang ingin menangani perhitungan moneter secara akurat di Java atau yang sedang mempertimbangkan mengadopsi BigDecimal dalam proyek mereka.
2. Apa Itu BigDecimal?
Gambaran Umum BigDecimal
BigDecimal adalah kelas di Java yang memungkinkan aritmetika desimal dengan presisi tinggi. Kelas ini berada dalam paket java.math dan dirancang khusus untuk perhitungan yang tidak toleran terhadap kesalahan seperti perhitungan 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 mengurangi kesalahan pembulatan dan aproksimasi.
Menangani Angka dengan Presisi Arbitrer
Karakteristik terbesar BigDecimal adalah “presisi arbitrer”. Baik bagian integer maupun desimal secara teoritis dapat menangani digit yang hampir tak terbatas, menghindari pembulatan atau kehilangan digit karena batas digit.
Sebagai contoh, angka besar berikut dapat ditangani secara akurat:
BigDecimal bigValue = new BigDecimal("12345678901234567890.12345678901234567890");
Kemampuan melakukan operasi aritmetika sambil mempertahankan presisi seperti ini adalah kekuatan utama BigDecimal.
Kasus Penggunaan Utama
BigDecimal direkomendasikan dalam situasi seperti:
- Perhitungan moneter — perhitungan bunga, tarif pajak dalam aplikasi keuangan
- Pemrosesan jumlah faktur / penawaran
- Perhitungan ilmiah/rekayasa yang memerlukan presisi tinggi
- Proses di mana akumulasi jangka panjang menyebabkan penumpukan kesalahan
Sebagai contoh, dalam sistem akuntansi dan perhitungan penggajian — di mana selisih 1 yen dapat menimbulkan kerugian besar atau sengketa — presisi BigDecimal sangat penting.
3. Penggunaan Dasar BigDecimal
Cara Membuat Instance BigDecimal
Berbeda dengan literal numerik biasa, BigDecimal sebaiknya dibuat dari string. Hal ini karena nilai yang dibuat dari double atau float mungkin sudah mengandung kesalahan aproksimasi biner.
Direkomendasikan (konstruksi dari String):
BigDecimal value = new BigDecimal("0.1");
Hindari (konstruksi dari double):
BigDecimal value = new BigDecimal(0.1); // may contain error
Cara Melakukan Aritmetika
BigDecimal tidak dapat digunakan dengan operator aritmetika biasa (+, -, *, /). Sebagai gantinya, metode khusus harus dipakai.
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.”
Menetapkan 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 bersifat immutable. Artinya — metode aritmetika (add, subtract, dll.) tidak mengubah nilai asli — mereka mengembalikan sebuah 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
Dalam BigDecimal, ada dua cara untuk membandingkan nilai: compareTo() dan equals(), dan kedua cara ini berperilaku 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)
Catatan: Untuk pemeriksaan kesetaraan numerik — seperti kesetaraan uang — compareTo() umumnya direkomendasikan.
Mengonversi Dari/Ke String
Dalam masukan pengguna dan impor file eksternal, konversi dengan tipe String umum dilakukan.
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 membuat 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 pada banyak operasi.
MathContext mc = new MathContext(4, RoundingMode.HALF_UP);
BigDecimal result = new BigDecimal("123.4567").round(mc); // 123.5
Juga dapat digunakan dalam aritmetika:
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 dapat mengirim 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 tak berhingga
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 tak berhingga, jika tidak ada mode pembulatan/skala yang diberikan, sebuah pengecualian akan dilempar.
Perbaikan: tentukan skala + mode pembulatan
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); // OK (3.33)
Kesalahan Saat Membuat Langsung Dari double
Passing a double secara langsung mungkin sudah mengandung kesalahan biner — menghasilkan nilai yang tidak 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, jadi hampir sama dengan new BigDecimal("0.1") — tetapi string adalah 100% paling aman.

Kesalahpahaman equals Karena Skala Tidak Cocok
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 yang Disebabkan oleh 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 (mis., 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 / pesanan.
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); // perkiraan 1,159,274.41
Point:
- Repeated calculations accumulate errors — BigDecimal avoids this.
Validation & Conversion of User Input
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
}
}
Points:
- Safely convert user-provided numeric strings.
- Validation + error fallback improves robustness.
7. Summary
The Role of BigDecimal
In Java’s numeric processing — especially monetary or precision-required logic — the BigDecimal class is indispensable. Errors inherent in float / double can be dramatically avoided by using BigDecimal.
This article covered fundamentals, arithmetic, comparisons, rounding, error handling, and real-world examples.
Key Review Points
BigDecimalhandles arbitrary-precision decimal — ideal for money and precision math- Initialization should be via string literal , e.g.
new BigDecimal("0.1") - Use
add(),subtract(),multiply(),divide(), and always specify rounding mode when dividing - Use
compareTo()for equality — understand difference vsequals() setScale()/MathContextlet you finely control scale + rounding- Real business logic cases include money, tax, quantity × unit price etc.
For Those About to Use BigDecimal
Although “handling numbers in Java” looks simple — precision / rounding / numeric error problems always exist behind it. BigDecimal is a tool that directly addresses those problems — mastering it lets you write more reliable code.
At first you may struggle with rounding modes — but with real project usage, it becomes natural.
Next chapter is an FAQ section summarizing common questions about BigDecimal — useful for review and specific semantic searches.
8. FAQ: Frequently Asked Questions About BigDecimal
Q1. Why should I use BigDecimal instead of float or double?
A1.
Because float/double represent numbers as binary approximations — decimal fractions cannot be represented exactly. This causes results such as “0.1 + 0.2 ≠ 0.3.”
BigDecimal preserves decimal values exactly — ideal for money or precision-critical logic.
Q2. What is the safest way to construct BigDecimal instances?
A2.
Always construct from string.
Bad (error):
new BigDecimal(0.1)
Correct:
new BigDecimal("0.1")
BigDecimal.valueOf(0.1) uses Double.toString() internally, so it’s almost same — but string is the safest.
Q3. Why does divide() throw an exception?
A3.
Because BigDecimal.divide() throws ArithmeticException when result is a non-terminating decimal.
Solution: specify scale + rounding mode
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP);
Q4. What’s the difference between compareTo() and equals()?
A4.
compareTo()checks numeric equality (scale ignored)equals()checks exact equality including scalenew BigDecimal("10.0").compareTo(new BigDecimal("10.00")); // → 0 new BigDecimal("10.0").equals(new BigDecimal("10.00")); // → false
Q5. How do I perform rounding?
A5.
Use setScale() with explicit rounding mode.
BigDecimal value = new BigDecimal("123.4567");
BigDecimal rounded = value.setScale(2, RoundingMode.HALF_UP); // 123.46
Main rounding modes:
RoundingMode.HALF_UP(round half up)RoundingMode.DOWN(round down)RoundingMode.UP(round up)
Q6. Can I check decimal digits (scale)?
A6.
Yes — use scale().
BigDecimal val = new BigDecimal("123.45");
System.out.println(val.scale()); // → 3
Q7. How should I handle null/empty input safely?
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;
}
}

