Français

Un guide complet sur le type BigInt de JavaScript, couvrant ses fonctionnalités, son utilisation et ses applications pour la gestion de l'arithmétique des grands entiers. Apprenez à surmonter les limites de JavaScript et à effectuer des calculs complexes avec précision.

JavaScript BigInt : Maîtriser l'arithmétique des grands entiers

JavaScript, bien qu'étant un langage polyvalent, a des limites lorsqu'il s'agit de traiter de très grands nombres entiers. Le type standard `Number` ne peut représenter avec précision les entiers que jusqu'à une certaine limite, connue sous le nom de `Number.MAX_SAFE_INTEGER`. Au-delà de cette limite, les calculs deviennent imprécis, entraînant des résultats inattendus. C'est là que BigInt vient à la rescousse. Introduit dans ECMAScript 2020, BigInt est un objet intégré qui offre un moyen de représenter et de manipuler des entiers de taille arbitraire, dépassant les limitations du type `Number` standard.

Comprendre le besoin de BigInt

Avant BigInt, les développeurs JavaScript devaient s'appuyer sur des bibliothèques ou des implémentations personnalisées pour gérer les calculs avec de grands entiers. Ces solutions entraînaient souvent une surcharge de performance et une complexité accrue. L'introduction de BigInt a fourni un moyen natif et efficace de travailler avec de grands entiers, ouvrant des possibilités pour des applications dans divers domaines, notamment :

Créer des valeurs BigInt

Il existe deux manières principales de créer des valeurs BigInt en JavaScript :

  1. Utiliser le constructeur `BigInt()` : Ce constructeur peut convertir une valeur de type nombre, chaîne de caractères ou booléen en un BigInt.
  2. Utiliser le suffixe `n` : Ajouter `n` à un littéral entier crée un BigInt.

Exemples :

Utilisation du constructeur `BigInt()` :


const bigIntFromNumber = BigInt(12345678901234567890);
const bigIntFromString = BigInt("98765432109876543210");
const bigIntFromBoolean = BigInt(true); // Résultat : 1n
const bigIntFromFalseBoolean = BigInt(false); // Résultat : 0n

console.log(bigIntFromNumber); // Sortie : 12345678901234567890n
console.log(bigIntFromString); // Sortie : 98765432109876543210n
console.log(bigIntFromBoolean); // Sortie : 1n
console.log(bigIntFromFalseBoolean); // Sortie : 0n

Utilisation du suffixe `n` :


const bigIntLiteral = 12345678901234567890n;
console.log(bigIntLiteral); // Sortie : 12345678901234567890n

Remarque importante : Vous ne pouvez pas mélanger directement les valeurs BigInt et Number dans les opérations arithmétiques. Vous devez les convertir explicitement au même type avant d'effectuer des calculs. Tenter de les mélanger directement entraînera une `TypeError`.

Opérations arithmétiques avec BigInt

BigInt prend en charge la plupart des opérateurs arithmétiques standard, notamment :

Exemples :


const a = 12345678901234567890n;
const b = 98765432109876543210n;

const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // Remarque : La division tronque vers zéro
const remainder = a % 7n;
const power = a ** 3n; // L'exponentiation fonctionne comme prévu

console.log("Somme :", sum); // Sortie : Somme : 111111111011111111100n
console.log("Différence :", difference); // Sortie : Différence : -86419753208641975320n
console.log("Produit :", product); // Sortie : Produit : 1219326311370217957951669538098765432100n
console.log("Quotient :", quotient); // Sortie : Quotient : 6172839450617283945n
console.log("Reste :", remainder); // Sortie : Reste : 5n
console.log("Puissance :", power); // Sortie : Puissance : 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n

Considérations importantes :

Opérateurs de comparaison

Vous pouvez utiliser les opérateurs de comparaison standard (`==`, `!=`, `<`, `>`, `<=`, `>=`) pour comparer des valeurs BigInt avec d'autres valeurs BigInt ou même avec des valeurs Number. Cependant, soyez attentif au potentiel de coercition de type.

Exemples :


const a = 10n;
const b = 20n;
const c = 10;

console.log(a == b);   // Sortie : false
console.log(a != b);   // Sortie : true
console.log(a < b);    // Sortie : true
console.log(a > b);    // Sortie : false
console.log(a <= b);   // Sortie : true
console.log(a >= b);   // Sortie : false

console.log(a == c);   // Sortie : true (coercition de type)
console.log(a === c);  // Sortie : false (pas de coercition de type)

Meilleure pratique : Utilisez l'égalité stricte (`===`) et l'inégalité stricte (`!==`) pour éviter la coercition de type inattendue lors de la comparaison des valeurs BigInt et Number.

Conversion entre BigInt et Number

Bien que les opérations arithmétiques directes entre BigInt et Number ne soient pas autorisées, vous pouvez convertir entre les deux types. Cependant, soyez conscient de la perte potentielle de précision lors de la conversion d'un BigInt en Number si la valeur du BigInt dépasse `Number.MAX_SAFE_INTEGER`.

Exemples :


const bigIntValue = 9007199254740991n; // Number.MAX_SAFE_INTEGER
const numberValue = Number(bigIntValue); // Conversion de BigInt en Number
console.log(numberValue); // Sortie : 9007199254740991

const largerBigIntValue = 9007199254740992n; // Dépasse Number.MAX_SAFE_INTEGER
const largerNumberValue = Number(largerBigIntValue);
console.log(largerNumberValue); // Sortie : 9007199254740992 (peut être imprécis)

const numberToBigInt = BigInt(12345); // Conversion de Number en BigInt
console.log(numberToBigInt); // Sortie : 12345n

Cas d'utilisation et exemples

Cryptographie

Les algorithmes cryptographiques reposent souvent sur de très grands nombres premiers pour la sécurité. BigInt offre un moyen de représenter et de manipuler ces nombres efficacement.


// Exemple : Génération d'une paire de clés simple (non sécurisée)
function generateKeyPair() {
  const p = 281n; // Un nombre premier
  const q = 283n; // Un autre nombre premier
  const n = p * q; // Modulo
  const totient = (p - 1n) * (q - 1n); // Fonction indicatrice d'Euler

  // Choisir un e (exposant public) tel que 1 < e < totient et pgcd(e, totient) = 1
  const e = 17n;

  // Calculer d (exposant privé) tel que (d * e) % totient = 1
  let d = 0n;
  for (let i = 1n; i < totient; i++) {
    if ((i * e) % totient === 1n) {
      d = i;
      break;
    }
  }

  return {
    publicKey: { n, e },
    privateKey: { n, d },
  };
}

const keyPair = generateKeyPair();
console.log("Clé publique :", keyPair.publicKey);
console.log("Clé privée :", keyPair.privateKey);

Note : Ceci est un exemple simplifié à des fins de démonstration uniquement. La cryptographie du monde réel utilise des nombres premiers beaucoup plus grands et des algorithmes plus sophistiqués.

Calculs financiers

Lorsqu'on traite de grosses sommes d'argent, en particulier dans les transactions internationales, la précision est essentielle. BigInt peut prévenir les erreurs d'arrondi et garantir des calculs précis.


// Exemple : Calcul des intérêts composés
function calculateCompoundInterest(principal, rate, time) {
  const principalBigInt = BigInt(principal * 100); // Convertir en centimes
  const rateBigInt = BigInt(rate * 10000);       // Convertir en dix-millièmes de pourcent
  const timeBigInt = BigInt(time);

  let amount = principalBigInt;
  for (let i = 0n; i < timeBigInt; i++) {
    amount = amount * (10000n + rateBigInt) / 10000n;
  }

  const amountInDollars = Number(amount) / 100;
  return amountInDollars;
}

const principal = 1000000; // 1 000 000 $
const rate = 0.05;    // Taux d'intérêt de 5%
const time = 10;     // 10 ans

const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("Montant final :", finalAmount); // Sortie : Montant final : 1628894.6267774413 (approximativement)

Dans cet exemple, nous convertissons le principal et le taux en valeurs BigInt pour éviter les erreurs d'arrondi pendant le calcul. Le résultat est ensuite reconverti en Number pour l'affichage.

Travailler avec de grands ID

Dans les systèmes distribués, la génération d'ID uniques sur plusieurs serveurs peut être un défi. L'utilisation de BigInt vous permet de créer de très grands ID qui ont peu de chances d'entrer en collision.


// Exemple : Génération d'un ID unique basé sur l'horodatage et l'ID du serveur
function generateUniqueId(serverId) {
  const timestamp = BigInt(Date.now());
  const serverIdBigInt = BigInt(serverId);
  const random = BigInt(Math.floor(Math.random() * 1000)); // Ajouter un peu d'aléa

  // Combiner les valeurs pour créer un ID unique
  const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
  return uniqueId.toString(); // Retourner sous forme de chaîne pour une manipulation facile
}

const serverId = 123; // ID de serveur d'exemple
const id1 = generateUniqueId(serverId);
const id2 = generateUniqueId(serverId);

console.log("ID Unique 1 :", id1);
console.log("ID Unique 2 :", id2);

BigInt et JSON

Les valeurs BigInt ne sont pas prises en charge nativement par JSON. Tenter de sérialiser un objet JavaScript contenant un BigInt avec `JSON.stringify()` entraînera une `TypeError`. Pour gérer les valeurs BigInt lorsque vous travaillez avec JSON, vous avez plusieurs options :

  1. Convertir en chaîne de caractères : Convertissez le BigInt en chaîne de caractères avant la sérialisation. C'est l'approche la plus courante et la plus simple.
  2. Sérialisation/Désérialisation personnalisée : Utilisez une fonction de sérialisation/désérialisation personnalisée pour gérer les valeurs BigInt.

Exemples :

Conversion en chaîne de caractères :


const data = {
  id: 12345678901234567890n,
  name: "Example Data",
};

// Convertir le BigInt en chaîne de caractères avant la sérialisation
data.id = data.id.toString();

const jsonData = JSON.stringify(data);
console.log(jsonData); // Sortie : {"id":"12345678901234567890","name":"Example Data"}

// Lors de la désérialisation, vous devrez reconvertir la chaîne en BigInt
const parsedData = JSON.parse(jsonData, (key, value) => {
  if (key === "id") {
    return BigInt(value);
  }
  return value;
});

console.log(parsedData.id); // Sortie : 12345678901234567890n

Sérialisation/Désérialisation personnalisée (avec `replacer` et `reviver`) :


const data = {
  id: 12345678901234567890n,
  name: "Example Data",
};

// Sérialisation personnalisée
const jsonData = JSON.stringify(data, (key, value) => {
  if (typeof value === 'bigint') {
    return value.toString();
  } else {
    return value;
  }
});

console.log(jsonData);

// Désérialisation personnalisée
const parsedData = JSON.parse(jsonData, (key, value) => {
    if (typeof value === 'string' && /^[0-9]+$/.test(value)) { //vérifier si c'est un nombre et une chaîne de caractères
      try {
        return BigInt(value);
      } catch(e) {
          return value;
      }
    }
    return value;
});

console.log(parsedData.id);

Compatibilité des navigateurs

BigInt est largement pris en charge dans les navigateurs modernes. Cependant, il est essentiel de vérifier la compatibilité avec les navigateurs ou environnements plus anciens. Vous pouvez utiliser un outil comme Can I use pour vérifier la prise en charge par les navigateurs. Si vous devez prendre en charge des navigateurs plus anciens, vous pourriez envisager d'utiliser un polyfill, mais sachez que les polyfills peuvent avoir un impact sur les performances.

Considérations sur les performances

Bien que BigInt offre un moyen puissant de travailler avec de grands entiers, il est important d'être conscient des implications potentielles sur les performances.

Par conséquent, n'utilisez BigInt que lorsque c'est nécessaire, et optimisez votre code pour les performances si vous effectuez un grand nombre d'opérations BigInt.

Conclusion

BigInt est un ajout précieux à JavaScript, permettant aux développeurs de gérer l'arithmétique des grands entiers avec précision. En comprenant ses fonctionnalités, ses limites et ses cas d'utilisation, vous pouvez tirer parti de BigInt pour créer des applications robustes et précises dans divers domaines, notamment la cryptographie, les calculs financiers et le calcul scientifique. N'oubliez pas de prendre en compte la compatibilité des navigateurs et les implications sur les performances lorsque vous utilisez BigInt dans vos projets.

Pour aller plus loin

Ce guide offre un aperçu complet de BigInt en JavaScript. Explorez les ressources liées pour des informations plus approfondies et des techniques avancées.

JavaScript BigInt : Maîtriser l'arithmétique des grands entiers en JavaScript | MLOG