Nederlands

Een complete gids voor JavaScript's BigInt, over functies, gebruik en toepassingen voor grote getallen. Overwin de beperkingen van JavaScript voor precieze berekeningen.

JavaScript BigInt: Grote Integer Aritmetiek Beheersen

JavaScript, hoewel een veelzijdige taal, heeft beperkingen bij het omgaan met zeer grote gehele getallen. Het standaard `Number`-type kan slechts gehele getallen tot een bepaalde limiet, bekend als `Number.MAX_SAFE_INTEGER`, nauwkeurig weergeven. Boven deze limiet worden berekeningen onnauwkeurig, wat leidt tot onverwachte resultaten. Dit is waar BigInt te hulp schiet. Geïntroduceerd in ECMAScript 2020, is BigInt een ingebouwd object dat een manier biedt om gehele getallen van willekeurige grootte weer te geven en te manipuleren, waarmee de beperkingen van het standaard `Number`-type worden overschreden.

De Noodzaak van BigInt Begrijpen

Voor BigInt moesten JavaScript-ontwikkelaars vertrouwen op bibliotheken of aangepaste implementaties om grote integer-berekeningen uit te voeren. Deze oplossingen brachten vaak prestatie-overhead en verhoogde complexiteit met zich mee. De introductie van BigInt bood een native en efficiënte manier om met grote gehele getallen te werken, wat mogelijkheden opende voor toepassingen in verschillende domeinen, waaronder:

BigInt-waarden Creëren

Er zijn twee primaire manieren om BigInt-waarden te creëren in JavaScript:

  1. Gebruik van de `BigInt()`-constructor: Deze constructor kan een getal, string of booleaanse waarde omzetten naar een BigInt.
  2. Gebruik van het `n`-achtervoegsel: Het toevoegen van `n` aan een letterlijk geheel getal creëert een BigInt.

Voorbeelden:

Gebruik van de `BigInt()`-constructor:


const bigIntFromNumber = BigInt(12345678901234567890);
const bigIntFromString = BigInt("98765432109876543210");
const bigIntFromBoolean = BigInt(true); // Resulteert in 1n
const bigIntFromFalseBoolean = BigInt(false); // Resulteert in 0n

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

Gebruik van het `n`-achtervoegsel:


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

Belangrijke opmerking: U kunt BigInt- en Number-waarden niet direct mengen in rekenkundige operaties. U moet ze expliciet naar hetzelfde type converteren voordat u berekeningen uitvoert. Pogingen om ze direct te mengen resulteren in een `TypeError`.

Rekenkundige Operaties met BigInt

BigInt ondersteunt de meeste standaard rekenkundige operatoren, waaronder:

Voorbeelden:


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

const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // Opmerking: Deling kapt af richting nul
const remainder = a % 7n;
const power = a ** 3n; // Machtsverheffen werkt zoals verwacht

console.log("Som:", sum); // Output: Sum: 111111111011111111100n
console.log("Verschil:", difference); // Output: Difference: -86419753208641975320n
console.log("Product:", product); // Output: Product: 1219326311370217957951669538098765432100n
console.log("Quotiënt:", quotient); // Output: Quotient: 6172839450617283945n
console.log("Rest:", remainder); // Output: Remainder: 5n
console.log("Macht:", power); // Output: Power: 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n

Belangrijke Overwegingen:

Vergelijkingsoperatoren

U kunt standaard vergelijkingsoperatoren (`==`, `!=`, `<`, `>`, `<=`, `>=`) gebruiken om BigInt-waarden te vergelijken met andere BigInt-waarden of zelfs met Number-waarden. Wees echter bedacht op de mogelijkheid van typeconversie.

Voorbeelden:


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

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

console.log(a == c);   // Output: true (typeconversie)
console.log(a === c);  // Output: false (geen typeconversie)

Beste Praktijk: Gebruik strikte gelijkheid (`===`) en strikte ongelijkheid (`!==`) om onverwachte typeconversie te vermijden bij het vergelijken van BigInt- en Number-waarden.

Converteren tussen BigInt en Number

Hoewel directe rekenkundige operaties tussen BigInt en Number niet zijn toegestaan, kunt u tussen de twee typen converteren. Wees u echter bewust van het mogelijke verlies van precisie bij het converteren van een BigInt naar een Number als de BigInt-waarde `Number.MAX_SAFE_INTEGER` overschrijdt.

Voorbeelden:


const bigIntValue = 9007199254740991n; // Number.MAX_SAFE_INTEGER
const numberValue = Number(bigIntValue); // BigInt naar Number converteren
console.log(numberValue); // Output: 9007199254740991

const largerBigIntValue = 9007199254740992n; // Overschrijdt Number.MAX_SAFE_INTEGER
const largerNumberValue = Number(largerBigIntValue);
console.log(largerNumberValue); // Output: 9007199254740992 (kan onnauwkeurig zijn)

const numberToBigInt = BigInt(12345); // Number naar BigInt converteren
console.log(numberToBigInt); // Output: 12345n

Toepassingen en Voorbeelden

Cryptografie

Cryptografische algoritmen vertrouwen vaak op zeer grote priemgetallen voor beveiliging. BigInt biedt een manier om deze getallen efficiënt weer te geven en te manipuleren.


// Voorbeeld: Een eenvoudig (onveilig) sleutelpaar genereren
function generateKeyPair() {
  const p = 281n; // Een priemgetal
  const q = 283n; // Een ander priemgetal
  const n = p * q; // Modulus
  const totient = (p - 1n) * (q - 1n); // Euler's totiëntfunctie

  // Kies een e (publieke exponent) zodat 1 < e < totiënt en ggd(e, totiënt) = 1
  const e = 17n;

  // Bereken d (private exponent) zodat (d * e) % totiënt = 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("Publieke Sleutel:", keyPair.publicKey);
console.log("Private Sleutel:", keyPair.privateKey);

Opmerking: Dit is slechts een vereenvoudigd voorbeeld voor demonstratiedoeleinden. Echte cryptografie maakt gebruik van veel grotere priemgetallen en geavanceerdere algoritmen.

Financiële Berekeningen

Bij het omgaan met grote geldbedragen, vooral bij internationale transacties, is precisie cruciaal. BigInt kan afrondingsfouten voorkomen en zorgen voor nauwkeurige berekeningen.


// Voorbeeld: Samengestelde rente berekenen
function calculateCompoundInterest(principal, rate, time) {
  const principalBigInt = BigInt(principal * 100); // Omzetten naar centen
  const rateBigInt = BigInt(rate * 10000);       // Omzetten naar tienduizendsten van een procent
  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;    // 5% rentevoet
const time = 10;     // 10 jaar

const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("Eindbedrag:", finalAmount); // Output: Final Amount: 1628894.6267774413 (ongeveer)

In dit voorbeeld converteren we de hoofdsom en de rentevoet naar BigInt-waarden om afrondingsfouten tijdens de berekening te voorkomen. Het resultaat wordt vervolgens teruggeconverteerd naar een Number voor weergave.

Werken met Grote ID's

In gedistribueerde systemen kan het genereren van unieke ID's over meerdere servers een uitdaging zijn. Met BigInt kunt u zeer grote ID's creëren die waarschijnlijk niet zullen conflicteren.


// Voorbeeld: Een unieke ID genereren op basis van tijdstempel en server-ID
function generateUniqueId(serverId) {
  const timestamp = BigInt(Date.now());
  const serverIdBigInt = BigInt(serverId);
  const random = BigInt(Math.floor(Math.random() * 1000)); // Voeg een beetje willekeur toe

  // Combineer de waarden om een unieke ID te creëren
  const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
  return uniqueId.toString(); // Retourneer als string voor eenvoudige verwerking
}

const serverId = 123; // Voorbeeld server-ID
const id1 = generateUniqueId(serverId);
const id2 = generateUniqueId(serverId);

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

BigInt en JSON

BigInt-waarden worden niet native ondersteund door JSON. Een poging om een JavaScript-object met een BigInt te serialiseren met `JSON.stringify()` resulteert in een `TypeError`. Om BigInt-waarden te verwerken bij het werken met JSON, heeft u een paar opties:

  1. Converteren naar String: Converteer de BigInt naar een string voordat u serialiseert. Dit is de meest gebruikelijke en eenvoudige aanpak.
  2. Aangepaste Serialisatie/Deserialisatie: Gebruik een aangepaste serialisatie/deserialisatie-functie om BigInt-waarden te verwerken.

Voorbeelden:

Converteren naar String:


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

// Converteer BigInt naar string voor het serialiseren
data.id = data.id.toString();

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

// Bij het deserialiseren moet u de string weer terug converteren naar een BigInt
const parsedData = JSON.parse(jsonData, (key, value) => {
  if (key === "id") {
    return BigInt(value);
  }
  return value;
});

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

Aangepaste Serialisatie/Deserialisatie (met `replacer` en `reviver`):


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

// Aangepaste serialisatie
const jsonData = JSON.stringify(data, (key, value) => {
  if (typeof value === 'bigint') {
    return value.toString();
  } else {
    return value;
  }
});

console.log(jsonData);

// Aangepaste deserialisatie
const parsedData = JSON.parse(jsonData, (key, value) => {
    if (typeof value === 'string' && /^[0-9]+$/.test(value)) { // controleer of het een getal en een string is
      try {
        return BigInt(value);
      } catch(e) {
          return value;
      }
    }
    return value;
});

console.log(parsedData.id);

Browsercompatibiliteit

BigInt wordt breed ondersteund in moderne browsers. Het is echter essentieel om de compatibiliteit voor oudere browsers of omgevingen te controleren. U kunt een tool zoals Can I use gebruiken om de browserondersteuning te verifiëren. Als u oudere browsers moet ondersteunen, kunt u overwegen een polyfill te gebruiken, maar wees u ervan bewust dat polyfills de prestaties kunnen beïnvloeden.

Prestatieoverwegingen

Hoewel BigInt een krachtige manier biedt om met grote gehele getallen te werken, is het belangrijk om u bewust te zijn van de mogelijke prestatie-implicaties.

Gebruik BigInt daarom alleen wanneer dat nodig is, en optimaliseer uw code voor prestaties als u een groot aantal BigInt-operaties uitvoert.

Conclusie

BigInt is een waardevolle toevoeging aan JavaScript, die ontwikkelaars in staat stelt om met precisie grote integer-aritmetiek te hanteren. Door de functies, beperkingen en toepassingen te begrijpen, kunt u BigInt benutten om robuuste en nauwkeurige applicaties te bouwen in verschillende domeinen, waaronder cryptografie, financiële berekeningen en wetenschappelijke berekeningen. Vergeet niet om rekening te houden met browsercompatibiliteit en prestatie-implicaties bij het gebruik van BigInt in uw projecten.

Verder Onderzoek

Deze gids biedt een uitgebreid overzicht van BigInt in JavaScript. Verken de gelinkte bronnen voor meer diepgaande informatie en geavanceerde technieken.