Comment formater des nombres à 2 décimales en JavaScript
Afficher des nombres avec exactement 2 décimales pour les prix, pourcentages et mesures
Introduction
De nombreuses applications doivent afficher des nombres avec un nombre fixe de décimales. Les prix affichent généralement deux décimales comme 19,99 €. Les pourcentages s'affichent souvent comme 45,50 %. Les mesures utilisent des décimales cohérentes pour une meilleure lisibilité, comme 3,14 mètres.
Contrôler les décimales assure une cohérence visuelle dans toute votre application. Sans formatage explicite, JavaScript affiche les nombres avec un nombre variable de décimales selon leur valeur réelle. Le nombre 5 s'affiche comme "5" tandis que 5,5 s'affiche comme "5,5", créant un alignement et une apparence incohérents.
Cette leçon montre comment formater les nombres à exactement 2 décimales, ou jusqu'à 2 décimales, d'une manière qui respecte les conventions des différentes locales.
Utilisation de toFixed() pour le formatage de base
La méthode toFixed() convertit un nombre en chaîne de caractères avec un nombre spécifié de décimales. Passez le nombre de décimales comme argument.
const price = 19.9;
const formatted = price.toFixed(2);
console.log(formatted);
// Résultat : "19.90"
La méthode affiche toujours exactement 2 décimales. Si le nombre a moins de décimales, toFixed() complète avec des zéros. S'il a plus de décimales, la méthode arrondit à 2 décimales.
const examples = [5, 5.5, 5.555, 5.999];
examples.forEach(num => {
console.log(num.toFixed(2));
});
// Résultat :
// "5.00"
// "5.50"
// "5.56"
// "6.00"
La méthode toFixed() renvoie une chaîne de caractères, pas un nombre. C'est intentionnel car les zéros finaux ont une signification pour l'affichage mais seraient perdus si renvoyés comme un nombre.
Le problème de locale avec toFixed()
La méthode toFixed() utilise toujours un point comme séparateur décimal, quelle que soit la locale de l'utilisateur. De nombreux pays utilisent une virgule comme séparateur décimal au lieu d'un point.
const price = 19.99;
console.log(price.toFixed(2));
// Résultat : "19.99" (utilise toujours un point)
Pour les utilisateurs en Allemagne, France, Espagne et de nombreux autres pays, cela semble incorrect. Ils s'attendent à voir "19,99" au lieu de "19.99". La méthode toFixed() ne peut pas produire une sortie adaptée à la locale.
Pour formater correctement les nombres pour différentes locales, utilisez l'API Intl.NumberFormat.
Utilisation d'Intl.NumberFormat pour un formatage adapté à la locale
L'API Intl.NumberFormat formate les nombres selon les conventions de locale. Créez un formateur avec une locale et des options, puis appelez sa méthode format() avec un nombre.
const formatter = new Intl.NumberFormat("de-DE", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const price = 19.99;
console.log(formatter.format(price));
// Résultat : "19,99" (utilise la virgule pour la locale allemande)
Le même formateur produit des résultats différents selon les locales.
const price = 19.99;
const usFormatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const deFormatter = new Intl.NumberFormat("de-DE", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(usFormatter.format(price));
// Résultat : "19.99"
console.log(deFormatter.format(price));
// Résultat : "19,99"
Le séparateur décimal change automatiquement en fonction de la locale.
Formatage avec exactement 2 décimales
Pour afficher exactement 2 décimales, définissez à la fois minimumFractionDigits et maximumFractionDigits à 2. Cela garantit que le résultat a toujours 2 décimales, en complétant avec des zéros si nécessaire et en arrondissant lorsque le nombre a plus de précision.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Résultat : "5.00"
console.log(formatter.format(5.5));
// Résultat : "5.50"
console.log(formatter.format(5.555));
// Résultat : "5.56"
L'option minimumFractionDigits contrôle les zéros finaux. Sans elle, les nombres avec moins de décimales n'afficheraient pas les zéros.
const withoutMinimum = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 2
});
console.log(withoutMinimum.format(5));
// Résultat : "5"
const withMinimum = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(withMinimum.format(5));
// Résultat : "5.00"
Définir les deux options à la même valeur garantit un nombre constant de décimales pour tous les nombres.
Formatage avec jusqu'à 2 décimales
Parfois, vous souhaitez afficher des décimales uniquement lorsque c'est nécessaire, jusqu'à un maximum de 2. Définissez maximumFractionDigits à 2 et minimumFractionDigits à 0 ou omettez-le complètement.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 0,
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Résultat : "5"
console.log(formatter.format(5.5));
// Résultat : "5.5"
console.log(formatter.format(5.555));
// Résultat : "5.56"
Cette approche supprime les zéros finaux mais limite toujours la précision à 2 décimales. Elle fonctionne bien pour afficher des mesures ou des statistiques où les zéros finaux n'ajoutent aucune information.
La valeur par défaut de minimumFractionDigits est 0 pour le formatage de nombres simples, vous pouvez donc l'omettre.
const formatter = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Résultat : "5"
console.log(formatter.format(5.5));
// Résultat : "5.5"
Réutilisation des formateurs pour une meilleure performance
La création d'une nouvelle instance Intl.NumberFormat est relativement coûteuse. Si vous formatez de nombreux nombres avec les mêmes options, créez le formateur une seule fois et réutilisez-le.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const prices = [19.99, 29.5, 99, 149.999];
prices.forEach(price => {
console.log(formatter.format(price));
});
// Résultat :
// "19.99"
// "29.50"
// "99.00"
// "150.00"
Ce modèle est plus efficace que la création d'un nouveau formateur pour chaque nombre.
Quand utiliser chaque approche
Utilisez exactement 2 décimales lors de l'affichage des prix, des montants en devise, ou de toute valeur où les décimales ont une signification sémantique. Afficher "5,00 €" au lieu de "5 €" indique une précision et correspond aux attentes des utilisateurs pour les prix.
Utilisez jusqu'à 2 décimales lors de l'affichage de statistiques, de mesures ou de valeurs calculées où les zéros finaux n'ajoutent aucune information. Afficher "5 mètres" au lieu de "5,00 mètres" est plus clair et plus lisible.
Utilisez toFixed() uniquement lorsque vous êtes certain que tous vos utilisateurs utilisent la même convention de séparateur décimal, ou lorsque le résultat n'est pas destiné à l'utilisateur final. Pour les applications internationalisées, préférez Intl.NumberFormat.
Utilisation de la locale préférée de l'utilisateur
Au lieu de coder en dur une locale, utilisez les préférences linguistiques du navigateur de l'utilisateur. La propriété navigator.language fournit la locale préférée de l'utilisateur.
const formatter = new Intl.NumberFormat(navigator.language, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const price = 19.99;
console.log(formatter.format(price));
// Le résultat varie selon la locale de l'utilisateur
// Pour en-US : "19.99"
// Pour de-DE : "19,99"
// Pour fr-FR : "19,99"
Vous pouvez également passer le tableau complet navigator.languages pour permettre à l'API Intl de sélectionner la première locale prise en charge parmi les préférences de l'utilisateur.
const formatter = new Intl.NumberFormat(navigator.languages, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
Cette approche fournit une solution de repli automatique si la première préférence de l'utilisateur n'est pas prise en charge.