BigDecimal în Java

Număr zecimal exact, fără erori de rotunjire ca la double; se folosește pentru bani, prețuri și calcule financiare.

Sintaxă
import java.math.BigDecimal;

BigDecimal a = new BigDecimal("19.99");
BigDecimal b = BigDecimal.valueOf(19.99);
BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN
int scale()
String toPlainString()

Ce face BigDecimal

double ține numerele în baza 2 și nu poate reprezenta exact valori ca 0,1 sau 0,2. De aceea 0.1 + 0.2 dă 0.30000000000000004. BigDecimal ține numărul ca un întreg plus o scală (câte cifre sunt după virgulă), deci 0.1 este exact 1 × 10−1.

Creezi un BigDecimal din text (new BigDecimal("19.99")) sau cu BigDecimal.valueOf(...). Evită new BigDecimal(0.1) cu double: primești valoarea binară exactă, cu zeci de cifre.

Obiectele sunt imutabile: a.add(b) nu schimbă a, ci returnează un număr nou. Operatorii +, -, *, / nu funcționează; folosești metodele add, subtract, multiply, divide.

Parametri

Parametru Descriere
text Numărul ca text, cu punct zecimal: "1250.50".

Ce returnează

Un obiect BigDecimal imutabil.

Exemple

Exemplul 1: double față de BigDecimal

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        System.out.println("double:     " + (0.1 + 0.2));
        BigDecimal a = new BigDecimal("0.1");
        BigDecimal b = new BigDecimal("0.2");
        System.out.println("BigDecimal: " + a.add(b));
        System.out.println("new BigDecimal(0.1) = " + new BigDecimal(0.1));
    }
}

Rezultat

double:     0.30000000000000004
BigDecimal: 0.3
new BigDecimal(0.1) = 0.1000000000000000055511151231257827021181583404541015625

Exemplul 2: Totalul unui coș de cumpărături

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        String[] preturi = {"19.99", "4.50", "129.90", "0.61"};
        BigDecimal total = BigDecimal.ZERO;
        for (String p : preturi) {
            total = total.add(new BigDecimal(p));
        }
        System.out.println("Total: " + total + " lei");
        System.out.println("Scala (cifre după virgulă): " + total.scale());
    }
}

Rezultat

Total: 155.00 lei
Scala (cifre după virgulă): 2

Exemplul 3: Scală și scriere fără exponent

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal mic = new BigDecimal("0.00000012");
        BigDecimal mare = new BigDecimal("1.5E+7");
        System.out.println(mic + " -> " + mic.toPlainString());
        System.out.println(mare + " -> " + mare.toPlainString());
        System.out.println("Scale: " + new BigDecimal("12.500").scale() + ", fără zerouri: "
            + new BigDecimal("12.500").stripTrailingZeros());
    }
}

Rezultat

1.2E-7 -> 0.00000012
1.5E+7 -> 15000000
Scale: 3, fără zerouri: 12.5

Greșeli frecvente

  • Folosești double pentru bani. Erorile mici se adună la sume mari și la rotunjiri; folosește BigDecimal (sau un long cu bani).
  • Scrii new BigDecimal(0.1). Folosește new BigDecimal("0.1") sau BigDecimal.valueOf(0.1).
  • Scrii total.add(pret); fără să păstrezi rezultatul. total rămâne neschimbat.

Comenzi înrudite

  • BigDecimal.valueOf: Creează un BigDecimal dintr-un long sau dintr-un double, folosind forma lui zecimală scurtă (0.1 rămâne 0.1).
  • BigDecimal.add: Adunare, scădere și înmulțire exactă între BigDecimal; fiecare returnează un număr nou.
  • BigDecimal.divide: Împărțire între BigDecimal; când rezultatul are zecimale infinite (10/3) trebuie să dai scala și modul de rotunjire.
  • BigDecimal.setScale: Rotunjește (sau completează cu zerouri) un BigDecimal la un număr fix de zecimale: setScale(2, RoundingMode.HALF_UP).
  • BigDecimal.compareTo: Compară valorile a două BigDecimal (negativ, 0, pozitiv); spre deosebire de equals, 2.0 și 2.00 sunt egale.
  • BigInteger: Întreg fără limită de mărime (cât îl lasă memoria); BigInteger.valueOf(n) îl creează dintr-un long.