Question 1Que se passe-t-il quand tu exécutes console.log(10 / 4); ?
Nombres et arithmétique — le type Number et Math
Le type Number : opérations, modulo et exposant, arrondis avec Math, toFixed, erreurs de calcul décimal.
Une grande partie de ce qu'une appli web calcule se ramène à des nombres — un sous-total de commande, une taxe de vente, des frais de port, des points gagnés. JavaScript n'a pas de types séparés pour les entiers et les décimaux ; il traite les deux avec le même type Number.
Cet article couvre les opérateurs arithmétiques, dont le modulo et l'exposant, l'arrondi avec Math, l'alignement des chiffres avec toFixed, et les erreurs de précision décimale qui piègent les gens dans les calculs d'argent.
Un seul type Number — Number et opérateurs arithmétiques
Certains langages séparent les entiers et les décimaux en types distincts. Cette notion de « genre de valeur » s'appelle un type (la classification d'une valeur — si c'est un nombre, du texte, etc.).
JavaScript ne fait aucune distinction entre entiers et décimaux — 1200 et 0.08 sont tous les deux le même type Number (le type qui représente les nombres). Tu ne choisis jamais de type en déclarant une variable, mais la contrepartie, c'est que diviser deux entiers peut laisser un résultat décimal.
Les symboles qui pilotent un calcul s'appellent des opérateurs arithmétiques (des symboles qui représentent un calcul entre valeurs). Au-delà de l'addition +, la soustraction -, la multiplication *, et la division /, il y a % pour le reste d'une division et ** pour les exposants.
% renvoie le reste, et ** renvoie la puissance.console.log(1200 + 300); // 1500
console.log(1200 - 300); // 900
console.log(1200 * 3); // 3600
// Même avec deux entiers, un reste décimal subsiste si ça ne tombe pas juste
console.log(7 / 2); // 3.5
// % est le reste, ** est l'exponentiation
console.log(7 % 2); // 1
console.log(2 ** 10); // 1024
% est pratique pour trouver un reliquat, ou « le reste quand on découpe en groupes de taille fixe ». Pour un total de 4380, 4380 % 100 te donne 80 — le montant restant une fois compté en unités de 100.
** te donne les exposants, permettant de calculer des choses comme 2 ** 10 — le nombre d'octets dans un kilo-octet.
Arrondir avec Math — floor, ceiling et le plus proche
Tu ne peux pas mettre la moyenne, 1903.3333333333333, directement sur une facture. Les montants et les compteurs doivent être arrondis à un nombre entier à un moment donné, et si tu arrondis vers le bas, vers le haut, ou à la valeur la plus proche dépend des règles métier.
JavaScript regroupe ces fonctions d'arrondi sous Math.
Présentons d'abord le terme fonction (une unité nommée qui exécute un traitement fixe sur une valeur que tu lui passes, et renvoie un résultat). Récupérer un résultat à partir d'une valeur passée s'appelle « appeler » la fonction et la faire « renvoyer » une valeur.
Une fonction sous Math (une collection intégrée de fonctions numériques de JavaScript) s'appelle en écrivant Math, un point, puis le nom de la fonction — comme Math.floor(1903.33).
Math.floor arrondit un décimal vers le bas, Math.ceil l'arrondit vers le haut, et Math.round arrondit au nombre entier le plus proche. Les trois renvoient simplement un nouveau nombre — la variable que tu as passée reste inchangée.
const points = 149.8; // Points calculés à partir du montant d'achat
console.log(Math.floor(points)); // 149 arrondi vers le bas
console.log(Math.ceil(points)); // 150 arrondi vers le haut
console.log(Math.round(points)); // 150 arrondi au plus proche
console.log(points); // 149.8 la valeur d'origine ne change pas
// max renvoie la plus grande des valeurs que tu lui passes
console.log(Math.max(0, 5000 - 5200)); // 0
Une autre fonction utile en dehors de l'arrondi est Math.max. Elle renvoie la plus grande des valeurs que tu lui passes, donc Math.max(0, -120) vaut 0.
Ça te donne un plancher pour un calcul que tu ne veux pas voir descendre en dessous de zéro — utile pour quelque chose comme « combien manque-t-il pour la livraison gratuite ».
Aligner les chiffres avec toFixed — ça renvoie une chaîne
Parfois, comme avec un montant moyen, tu veux décider à l'avance du nombre de chiffres affichés. Afficher 1903.3333333333333 tel quel est difficile à lire, donc tu le nettoies à une décimale et affiches 1903.3.
Utilise toFixed pour ça.
toFixed est une méthode (une fonction que tu appelles en écrivant un point après une valeur) — tu l'appelles avec un point après un nombre. Une valeur passée entre les parenthèses s'appelle un argument (une valeur passée entre les parenthèses d'une fonction ou d'une méthode). Passe-lui le nombre de décimales à garder, comme dans toFixed(1), et elle arrondit au chiffre suivant et renvoie le résultat gardé à ce nombre de décimales. Mais ce qui revient est une chaîne, pas un nombre. Utilise-la seulement juste avant d'afficher une valeur — pour des calculs supplémentaires, utilise le nombre d'origine ou Math.round à la place.
Math.floor(value) passe une valeur à une fonction qui vit dans le conteneur Math ; value.toFixed(digits) appelle une fonction que la valeur elle-même porte. Ce qui précède le point te dit quelle forme tu regardes.
const averageOrder = 1903.3333333333333; // Montant moyen par commande
console.log(averageOrder.toFixed(1)); // 1903.3 renvoyé sous forme de chaîne
console.log(averageOrder.toFixed(0)); // 1903 renvoyé sous forme de chaîne
// Pour continuer à calculer, arrondis en restant un nombre
console.log(Math.round(averageOrder * 10) / 10); // 1903.3 toujours un nombre
Le résultat de toFixed n'est que pour l'affichage
Puisque ce que renvoie toFixed est une chaîne, additionner ou multiplier ce résultat se comporte différemment de ce que ferait un nombre. La différence entre chaînes et nombres, et comment vérifier laquelle tu as, sont couvertes dans l'article sur la conversion de type.
Erreur de précision décimale — pourquoi 0.1 + 0.2 n'est pas 0.3
Enchaîne assez de calculs impliquant des décimaux, et la réponse peut dériver légèrement. C'est ce qui cause des bugs comme un total décalé d'un centime, donc regardons pourquoi ça arrive et comment l'éviter avant que ça te morde.
Les ordinateurs stockent les nombres en binaire. 0.1 en décimal ne se divise pas exactement en binaire — ça devient une fraction infiniment répétée — donc c'est stocké comme une valeur différente, très proche à la place.
0.1 et 0.2 sont tous les deux stockés légèrement décalés, donc les additionner tombe légèrement à côté de 0.3 aussi.
console.log(0.1 + 0.2); // 0.30000000000000004
// Passe d'abord à l'échelle en entiers, calcule, puis reviens à l'échelle — pas de dérive
console.log((0.1 * 10 + 0.2 * 10) / 10); // 0.3
Stocke les montants comme des nombres entiers
Plus tu enchaînes d'additions décimales, plus la dérive s'accumule. Pour les montants d'argent, stocke-les en unités entières et ne divise que juste avant l'affichage — ça évite complètement cette erreur.
Valeurs de calculs échoués — NaN et Infinity
Quand un calcul ne fonctionne pas, JavaScript ne s'arrête pas — il renvoie une valeur spéciale et continue. Beaucoup de bugs où un total apparaît vide ou un montant s'affiche mal viennent de ce genre de valeur mélangée dans un calcul qui a juste continué de tourner.
Un résultat qui ne peut pas s'exprimer comme un nombre est NaN (abréviation de Not a Number — une valeur signifiant que le résultat n'a pas pu devenir un nombre). 0 / 0, en essayant de faire la moyenne d'une journée sans commandes, en est un exemple.
Diviser par zéro dans l'autre sens, comme 5710 / 0, renvoie Infinity (une valeur représentant l'infini). Ni l'un ni l'autre ne s'arrête avec une erreur, donc tu pourrais ne pas le remarquer avant que ça s'affiche à l'écran.
const orderTotal = 5710;
const orderCount = 0; // Il y a eu 0 commande ce jour-là
console.log(orderTotal / orderCount); // Infinity
console.log(0 / 0); // NaN
// Une fois que NaN s'est glissé dedans, tout calcul après devient NaN aussi
console.log(0 / 0 + 1000); // NaN
Tout comme Math, Number regroupe son propre ensemble de fonctions liées aux nombres. Tu peux vérifier si une valeur est un nombre entier avec Number.isInteger. Number.isInteger(3) renvoie true et Number.isInteger(2.5) renvoie false — un booléen (une valeur représentant l'un de deux choix : si quelque chose est vrai) — donc c'est utile pour confirmer qu'une valeur comme un compteur n'autorise pas les décimales.
Comment vérifier si deux valeurs sont égales est couvert dans le prochain article, mais NaN est l'exception — il n'est même pas égal à lui-même avec cette méthode.
Donc vérifier NaN utilise une vérification dédiée à la place. C'est couvert, ainsi que la conversion de chaînes en nombres, dans l'article sur la conversion de type.
console.log(Number.isInteger(3)); // true
console.log(Number.isInteger(2.5)); // false
console.log(Number.isInteger(6 / 2)); // true une division exacte est un nombre entier
NaN et Infinity circulent dans le calcul suivant sans jamais s'arrêter sur une erreur. Quand un total ou une moyenne s'affiche mal, soupçonne d'abord une division par zéro — c'est généralement le moyen le plus rapide de trouver la cause.
Vérification des connaissances
Répondez à chaque question une par une.
Question 2Que renvoie l'appel de toFixed(2) sur un nombre ?
Question 3Qu'affiche console.log(0.1 + 0.2); ?