- 1 1. Introduction
- 2 2. Qu’est-ce que BigDecimal ?
- 3 3. Utilisation de base de BigDecimal
- 4 4. Utilisation Avancée de BigDecimal
- 5 5. Erreurs Courantes et Comment les Corriger
- 5.1 ArithmeticException : Expansion décimale non terminante
- 5.2 Erreurs Lors de la Construction Directement À Partir de double
- 5.3 Mauvaise compréhension de equals due à un décalage d’échelle
- 5.4 Résultats inattendus causés par une précision insuffisante
- 5.5 NumberFormatException lorsque la valeur d’entrée est invalide
- 6 6. Exemples d’utilisation pratiques
- 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. Introduction
Problèmes de précision dans les calculs numériques en Java
Dans la programmation Java, les calculs numériques sont effectués quotidiennement. Par exemple, calculer les prix des produits, déterminer les taxes ou les intérêts — ces opérations sont requises dans de nombreuses applications. Cependant, lorsque de tels calculs sont effectués en utilisant des types à virgule flottante tels que float ou double, des erreurs inattendues peuvent survenir.
Cela se produit parce que float et double représentent les valeurs comme des approximations binaires. Des valeurs telles que « 0.1 » ou « 0.2 », qui peuvent être exprimées avec précision en décimal, ne peuvent pas être représentées exactement en binaire — et par conséquent, de petites erreurs s’accumulent.
BigDecimal est essentiel pour les calculs monétaires ou de précision
De telles erreurs peuvent être critiques dans des domaines comme les calculs monétaires et les calculs scientifiques/ingénierie de précision. Par exemple, dans les calculs de facturation, même une différence de 1 yen peut entraîner des problèmes de crédibilité.
C’est là que la classe BigDecimal de Java excelle. BigDecimal peut gérer des nombres décimaux avec une précision arbitraire et en l’utilisant à la place de float ou double, les calculs numériques peuvent être effectués sans erreurs.
Ce que vous gagnerez de cet article
Dans cet article, nous expliquerons les bases de l’utilisation de BigDecimal en Java, les techniques avancées, ainsi que les erreurs courantes et les précautions de manière systématique.
Ceci est utile pour ceux qui souhaitent gérer les calculs monétaires avec précision en Java ou qui envisagent d’adopter BigDecimal dans leurs projets.
2. Qu’est-ce que BigDecimal ?
Aperçu de BigDecimal
BigDecimal est une classe en Java qui permet l’arithmétique décimale à haute précision. Elle appartient au package java.math et est conçue spécifiquement pour les calculs intolérants aux erreurs tels que les calculs financiers/comptables/fiscaux.
Avec les float et double de Java, les valeurs numériques sont stockées comme des approximations binaires — ce qui signifie que les décimales telles que « 0.1 » ou « 0.2 » ne peuvent pas être représentées exactement, ce qui est la source d’erreur. En revanche, BigDecimal stocke les valeurs sous forme de représentation décimale basée sur une chaîne, supprimant ainsi les erreurs d’arrondi et d’approximation.
Gestion des nombres à précision arbitraire
La plus grande caractéristique de BigDecimal est la « précision arbitraire ». Les parties entière et décimale peuvent théoriquement gérer un nombre virtuellement illimité de chiffres, évitant l’arrondi ou la perte de chiffres due aux contraintes de chiffres.
Par exemple, le grand nombre suivant peut être géré avec précision :
BigDecimal bigValue = new BigDecimal("12345678901234567890.12345678901234567890");
Pouvoir effectuer des opérations arithmétiques tout en préservant la précision comme cela est la principale force de BigDecimal.
Principaux cas d’utilisation
BigDecimal est recommandé dans des situations telles que :
- Calculs monétaires — intérêts, calculs de taux d’imposition dans les applications financières
- Traitement des montants de factures / devis
- Calculs scientifiques/ingénierie nécessitant une haute précision
- Processus où l’accumulation à long terme cause une accumulation d’erreurs
Par exemple, dans les systèmes comptables et les calculs de paie — où une différence de 1 yen peut entraîner de grandes pertes ou des litiges — la précision de BigDecimal est essentielle.
3. Utilisation de base de BigDecimal
Comment créer des instances BigDecimal
Contrairement aux littéraux numériques normaux, BigDecimal doit généralement être construit à partir d’une chaîne. C’est parce que les valeurs créées à partir de double ou float peuvent déjà contenir des erreurs d’approximation binaire.
Recommandé (construire à partir de String) :
BigDecimal value = new BigDecimal("0.1");
À éviter (construire à partir de double) :
BigDecimal value = new BigDecimal(0.1); // may contain error
Comment effectuer des opérations arithmétiques
BigDecimal ne peut pas être utilisé avec les opérateurs arithmétiques normaux (+, -, *, /). Au lieu de cela, des méthodes dédiées doivent être utilisées.
Addition (add)
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("2.3");
BigDecimal result = a.add(b); // 12.8
Soustraction (subtract)
BigDecimal result = a.subtract(b); // 8.2
Multiplication (multiply)
BigDecimal result = a.multiply(b); // 24.15
Division (divide) et Mode d’Arrondi
La division nécessite de la prudence. Si ce n’est pas divisible de manière égale, une ArithmeticException se produira à moins que le mode d’arrondi ne soit spécifié.
BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); // 3.33
Ici, nous spécifions « 2 décimales » et « arrondi demi vers le haut ».
Définition de l’Échelle et du Mode d’Arrondi avec setScale
setScale peut être utilisé pour arrondir à un nombre spécifié de chiffres.
BigDecimal value = new Big BigDecimal("123.456789");
BigDecimal rounded = value.setScale(2, RoundingMode.HALF_UP); // 123.46
Valeurs courantes de RoundingMode :
| 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 est Immuable
BigDecimal est immuable. Cela signifie — les méthodes arithmétiques (add, subtract, etc.) ne modifient pas la valeur originale — elles retournent une nouvelle instance.
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. Utilisation Avancée de BigDecimal
Comparaison des Valeurs : Différence Entre compareTo et equals
Dans BigDecimal, il y a deux façons de comparer les valeurs : compareTo() et equals(), et elles se comportent différemment.
compareTo()compare uniquement la valeur numérique (ignore l’échelle).equals()compare en incluant l’échelle (nombre de chiffres décimaux).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)
Point : Pour les vérifications d’égalité numérique — comme l’égalité monétaire — compareTo() est généralement recommandé.
Conversion Vers/Depuis String
Dans les entrées utilisateur et les imports de fichiers externes, la conversion avec des types String est courante.
String → BigDecimal
BigDecimal value = new Big BigDecimal("1234.56");
BigDecimal → String
String str = value.toString(); // "1234.56"
Utilisation de valueOf
Java possède également BigDecimal.valueOf(double val), mais cela contient également en interne l’erreur de double, donc la construction à partir d’une chaîne est toujours plus sûre.
BigDecimal unsafe = BigDecimal.valueOf(0.1); // contains internal error
Précision et Règles d’Arrondi via MathContext
MathContext permet de contrôler la précision et le mode d’arrondi en même temps — utile lors de l’application de règles communes à de nombreuses opérations.
MathContext mc = new MathContext(4, RoundingMode.HALF_UP);
BigDecimal result = new BigDecimal("123.4567").round(mc); // 123.5
Également utilisable en arithmétique :
BigDecimal a = new BigDecimal("10.456");
BigDecimal b = new BigDecimal("2.1");
BigDecimal result = a.multiply(b, mc); // 4-digit precision
Vérifications null et Initialisation Sûre
Les formulaires peuvent passer des valeurs null ou vides — le code de garde est standard.
String input = ""; // empty
BigDecimal value = (input == null || input.isEmpty()) ? BigDecimal.ZERO : new BigDecimal(input);
Vérification de l’Échelle de BigDecimal
Pour connaître les chiffres décimaux, utilisez scale() :
BigDecimal value = new BigDecimal("123.45");
System.out.println(value.scale()); // 3
5. Erreurs Courantes et Comment les Corriger
ArithmeticException : Expansion décimale non terminante
Exemple d’Erreur :
BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("3");
BigDecimal result = a.divide(b); // exception
Ceci est « 1 ÷ 3 » — comme cela devient une décimale non terminante, si aucun mode d’arrondi/échelle n’est donné, une exception est lancée.
Correction : spécifier l’échelle + mode d’arrondi
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); // OK (3.33)
Erreurs Lors de la Construction Directement À Partir de double
Passer directement un double peut déjà contenir une erreur binaire — produisant des valeurs inattendues.
Mauvais exemple :
BigDecimal val = new BigDecimal(0.1);
System.out.println(val); // 0.100000000000000005551115123...
Correct : Utiliser une chaîne
BigDecimal val = new BigDecimal("0.1"); // exact 0.1
Note : BigDecimal.valueOf(0.1) utilise Double.toString() en interne, donc c’est « presque identique » à new BigDecimal("0.1") — mais la chaîne est 100 % la plus sûre.

Mauvaise compréhension de equals due à un décalage d’échelle
Parce que equals() compare l’échelle, il peut renvoyer false même si les valeurs sont numériquement égales.
BigDecimal a = new BigDecimal("10.0");
BigDecimal b = new BigDecimal("10.00");
System.out.println(a.equals(b)); // false
Solution : utiliser compareTo() pour l’égalité numérique
System.out.println(a.compareTo(b)); // 0
Résultats inattendus causés par une précision insuffisante
Si vous utilisez setScale sans spécifier le mode d’arrondi — des exceptions peuvent survenir.
Mauvais exemple :
BigDecimal value = new BigDecimal("1.2567");
BigDecimal rounded = value.setScale(2); // exception
Solution :
BigDecimal rounded = value.setScale(2, RoundingMode.HALF_UP); // OK
NumberFormatException lorsque la valeur d’entrée est invalide
Si un texte invalide qui ne peut pas être analysé comme un nombre est passé (par ex., saisie utilisateur / champs CSV), une NumberFormatException se produira.
Solution : utiliser la gestion des exceptions
try {
BigDecimal value = new BigDecimal(userInput);
} catch (NumberFormatException e) {
// show error message or fallback logic
}
6. Exemples d’utilisation pratiques
Voici des scénarios réels démontrant comment BigDecimal peut être utilisé en pratique. En particulier dans les calculs financiers/comptables/fiscaux, l’importance d’une gestion numérique précise devient évidente.
Gestion des décimales dans les calculs de prix (arrondi des fractions)
Exemple : Calcul du prix incluant une taxe de consommation de 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
Points :
- Les résultats du calcul de la taxe sont souvent traités comme des nombres entiers, en utilisant
setScale(0, RoundingMode.HALF_UP)pour arrondir. - Le
doublea tendance à produire des erreurs —BigDecimalest recommandé.
Calculs de remise (% DE RÉDUCTION)
Exemple : remise de 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
Point : Les calculs de remise de prix ne doivent pas perdre de précision.
Calcul du prix unitaire × quantité (Scénario typique d’application métier)
Exemple : 298,5 yen × 7 articles
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
Points :
- Ajuster l’arrondi pour la multiplication fractionnaire.
- Important pour les systèmes comptables / de commande.
Calcul d’intérêts composés (exemple financier)
Exemple : intérêt annuel de 3 % × 5 ans
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("Après 5 ans : " + finalAmount); // environ 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; // traiter l'entrée invalide comme 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.
Toujours inclure vérifications de nullité + gestion des exceptions.
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;
}
}

