Norsk

En omfattende guide til JavaScripts BigInt-type, som dekker funksjoner, bruk og anvendelser i håndtering av store heltallsberegninger. Lær hvordan du overvinner JavaScripts begrensninger og utfører komplekse kalkulasjoner med presisjon.

JavaScript BigInt: Mestring av store heltallsberegninger

JavaScript er et allsidig språk, men har begrensninger når det gjelder håndtering av veldig store heltall. Standardtypen `Number` kan bare representere heltall nøyaktig opp til en viss grense, kjent som `Number.MAX_SAFE_INTEGER`. Utover denne grensen blir beregningene unøyaktige, noe som fører til uventede resultater. Det er her BigInt kommer til unnsetning. Introdusert i ECMAScript 2020, er BigInt et innebygd objekt som gir en måte å representere og manipulere heltall av vilkårlig størrelse, og overgår begrensningene til standardtypen `Number`.

Forstå behovet for BigInt

Før BigInt måtte JavaScript-utviklere stole på biblioteker eller egendefinerte implementasjoner for å håndtere store heltallsberegninger. Disse løsningene medførte ofte ytelsesutfordringer og økt kompleksitet. Innføringen av BigInt ga en innebygd og effektiv måte å jobbe med store heltall på, noe som åpnet for muligheter for applikasjoner innen ulike domener, inkludert:

Å skape BigInt-verdier

Det er to primære måter å skape BigInt-verdier i JavaScript:

  1. Bruke `BigInt()`-konstruktøren: Denne konstruktøren kan konvertere et tall, en streng eller en boolsk verdi til en BigInt.
  2. Bruke `n`-suffikset: Å legge til `n` etter et heltallsliteral skaper en BigInt.

Eksempler:

Bruke `BigInt()`-konstruktøren:


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

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

Bruke `n`-suffikset:


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

Viktig merknad: Du kan ikke blande BigInt- og Number-verdier direkte i aritmetiske operasjoner. Du må eksplisitt konvertere dem til samme type før du utfører beregninger. Forsøk på å blande dem direkte vil resultere i en `TypeError`.

Aritmetiske operasjoner med BigInt

BigInt støtter de fleste standard aritmetiske operatorer, inkludert:

Eksempler:


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

const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // Merk: Divisjon avkorter mot null
const remainder = a % 7n;
const power = a ** 3n; // Eksponentiering fungerer som forventet

console.log("Summe:", sum); // Output: Summe: 111111111011111111100n
console.log("Differanse:", difference); // Output: Differanse: -86419753208641975320n
console.log("Produkt:", product); // Output: Produkt: 1219326311370217957951669538098765432100n
console.log("Kvotient:", quotient); // Output: Kvotient: 6172839450617283945n
console.log("Rest:", remainder); // Output: Rest: 5n
console.log("Potens:", power); // Output: Potens: 1876412810291823000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n

Viktige hensyn:

Sammenligningsoperatorer

Du kan bruke standard sammenligningsoperatorer (`==`, `!=`, `<`, `>`, `<=`, `>=`) for å sammenligne BigInt-verdier med andre BigInt-verdier eller til og med med Number-verdier. Vær imidlertid oppmerksom på potensialet for typekonvertering (type coercion).

Eksempler:


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 (typekonvertering)
console.log(a === c);  // Output: false (ingen typekonvertering)

Beste praksis: Bruk streng likhet (`===`) og streng ulikhet (`!==`) for å unngå uventet typekonvertering når du sammenligner BigInt- og Number-verdier.

Konvertering mellom BigInt og Number

Selv om direkte aritmetiske operasjoner mellom BigInt og Number ikke er tillatt, kan du konvertere mellom de to typene. Vær imidlertid oppmerksom på potensielt tap av presisjon når du konverterer en BigInt til et Number hvis BigInt-verdien overstiger `Number.MAX_SAFE_INTEGER`.

Eksempler:


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

const largerBigIntValue = 9007199254740992n; // Overstiger Number.MAX_SAFE_INTEGER
const largerNumberValue = Number(largerBigIntValue);
console.log(largerNumberValue); // Output: 9007199254740992 (kan være upresis)

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

Bruksområder og eksempler

Kryptografi

Kryptografiske algoritmer er ofte avhengige av veldig store primtall for sikkerhet. BigInt gir en måte å representere og manipulere disse tallene effektivt.


// Eksempel: Genererer et enkelt (usikkert) nøkkelpar
function generateKeyPair() {
  const p = 281n; // Et primtall
  const q = 283n; // Et annet primtall
  const n = p * q; // Modulus
  const totient = (p - 1n) * (q - 1n); // Eulers totientfunksjon

  // Velg en e (offentlig eksponent) slik at 1 < e < totient og gcd(e, totient) = 1
  const e = 17n;

  // Beregn d (privat eksponent) slik at (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("Offentlig nøkkel:", keyPair.publicKey);
console.log("Privat nøkkel:", keyPair.privateKey);

Merk: Dette er et forenklet eksempel kun for demonstrasjonsformål. Ekte kryptografi bruker mye større primtall og mer sofistikerte algoritmer.

Finansielle beregninger

Når man håndterer store pengesummer, spesielt i internasjonale transaksjoner, er presisjon avgjørende. BigInt kan forhindre avrundingsfeil og sikre nøyaktige beregninger.


// Eksempel: Beregning av rentesrente
function calculateCompoundInterest(principal, rate, time) {
  const principalBigInt = BigInt(principal * 100); // Konverter til cent
  const rateBigInt = BigInt(rate * 10000);       // Konverter til ti-tusendeler av en prosent
  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% rente
const time = 10;     // 10 år

const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("Endelig beløp:", finalAmount); // Output: Endelig beløp: 1628894.6267774413 (omtrentlig)

I dette eksemplet konverterer vi hovedstolen og renten til BigInt-verdier for å unngå avrundingsfeil under beregningen. Resultatet konverteres deretter tilbake til et Number for visning.

Arbeid med store ID-er

I distribuerte systemer kan det være utfordrende å generere unike ID-er på tvers av flere servere. Ved å bruke BigInt kan du lage veldig store ID-er som har lav sannsynlighet for å kollidere.


// Eksempel: Genererer en unik ID basert på tidsstempel og server-ID
function generateUniqueId(serverId) {
  const timestamp = BigInt(Date.now());
  const serverIdBigInt = BigInt(serverId);
  const random = BigInt(Math.floor(Math.random() * 1000)); // Legg til litt tilfeldighet

  // Kombiner verdiene for å lage en unik ID
  const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
  return uniqueId.toString(); // Returner som en streng for enkel håndtering
}

const serverId = 123; // Eksempel på server-ID
const id1 = generateUniqueId(serverId);
const id2 = generateUniqueId(serverId);

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

BigInt og JSON

BigInt-verdier støttes ikke innebygd av JSON. Et forsøk på å serialisere et JavaScript-objekt som inneholder en BigInt ved hjelp av `JSON.stringify()` vil resultere i en `TypeError`. For å håndtere BigInt-verdier når du jobber med JSON, har du et par alternativer:

  1. Konverter til streng: Konverter BigInt til en streng før serialisering. Dette er den vanligste og enkleste tilnærmingen.
  2. Egendefinert serialisering/deserialisering: Bruk en egendefinert funksjon for serialisering/deserialisering for å håndtere BigInt-verdier.

Eksempler:

Konvertering til streng:


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

// Konverter BigInt til streng før serialisering
data.id = data.id.toString();

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

// Ved deserialisering må du konvertere strengen tilbake til en BigInt
const parsedData = JSON.parse(jsonData, (key, value) => {
  if (key === "id") {
    return BigInt(value);
  }
  return value;
});

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

Egendefinert serialisering/deserialisering (ved hjelp av `replacer` og `reviver`):


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

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

console.log(jsonData);

// Egendefinert deserialisering
const parsedData = JSON.parse(jsonData, (key, value) => {
    if (typeof value === 'string' && /^[0-9]+$/.test(value)) { // sjekk om det er et tall og en streng
      try {
        return BigInt(value);
      } catch(e) {
          return value;
      }
    }
    return value;
});

console.log(parsedData.id);

Nettleserkompatibilitet

BigInt er bredt støttet i moderne nettlesere. Det er imidlertid viktig å sjekke kompatibiliteten for eldre nettlesere eller miljøer. Du kan bruke et verktøy som Can I use for å verifisere nettleserstøtte. Hvis du trenger å støtte eldre nettlesere, kan du vurdere å bruke en polyfill, men vær klar over at polyfills kan påvirke ytelsen.

Ytelseshensyn

Selv om BigInt gir en kraftig måte å jobbe med store heltall på, er det viktig å være klar over potensielle ytelsesimplikasjoner.

Bruk derfor BigInt bare når det er nødvendig, og optimaliser koden din for ytelse hvis du utfører et stort antall BigInt-operasjoner.

Konklusjon

BigInt er et verdifullt tillegg til JavaScript, som gjør det mulig for utviklere å håndtere store heltallsberegninger med presisjon. Ved å forstå funksjonene, begrensningene og bruksområdene, kan du utnytte BigInt til å bygge robuste og nøyaktige applikasjoner innen ulike domener, inkludert kryptografi, finansielle beregninger og vitenskapelig databehandling. Husk å vurdere nettleserkompatibilitet og ytelsesimplikasjoner når du bruker BigInt i prosjektene dine.

Videre utforskning

Denne guiden gir en omfattende oversikt over BigInt i JavaScript. Utforsk de lenkede ressursene for mer dyptgående informasjon og avanserte teknikker.