Dansk

En omfattende guide til JavaScripts BigInt-type, der dækker dens funktioner, brug og anvendelser til håndtering af stor heltalsaritmetik. Lær at overvinde JavaScripts begrænsninger og udføre komplekse beregninger med præcision.

JavaScript BigInt: Beherskelse af stor heltalsaritmetik

Selvom JavaScript er et alsidigt sprog, har det begrænsninger, når det kommer til at håndtere meget store heltal. Standarden `Number`-typen kan kun repræsentere heltal præcist op til en vis grænse, kendt som `Number.MAX_SAFE_INTEGER`. Ud over denne grænse bliver beregninger upræcise, hvilket fører til uventede resultater. Det er her, BigInt kommer til undsætning. Introduceret i ECMAScript 2020 er BigInt et indbygget objekt, der giver en måde at repræsentere og manipulere heltal af vilkårlig størrelse på, hvilket overskrider begrænsningerne for standard `Number`-typen.

Forståelsen af behovet for BigInt

Før BigInt måtte JavaScript-udviklere stole på biblioteker eller brugerdefinerede implementeringer for at håndtere store heltalsberegninger. Disse løsninger medførte ofte et performancetab og øget kompleksitet. Introduktionen af BigInt gav en native og effektiv måde at arbejde med store heltal på, hvilket åbnede op for muligheder for applikationer inden for forskellige domæner, herunder:

Oprettelse af BigInt-værdier

Der er to primære måder at oprette BigInt-værdier på i JavaScript:

  1. Brug af `BigInt()`-konstruktøren: Denne konstruktør kan konvertere et tal, en streng eller en boolesk værdi til en BigInt.
  2. Brug af `n`-suffikset: At tilføje `n` til en heltalsliteral opretter en BigInt.

Eksempler:

Brug af `BigInt()`-konstruktøren:


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

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

Brug af `n`-suffikset:


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

Vigtig bemærkning: Du kan ikke blande BigInt- og Number-værdier direkte i aritmetiske operationer. Du skal eksplicit konvertere dem til den samme type, før du udfører beregninger. Forsøg på at blande dem direkte vil resultere i en `TypeError`.

Aritmetiske operationer med BigInt

BigInt understøtter de fleste af de almindelige aritmetiske operatorer, herunder:

Eksempler:


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

const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // Bemærk: Division afkorter mod nul
const remainder = a % 7n;
const power = a ** 3n; // Eksponentiering virker som forventet

console.log("Sum:", sum); // Output: Sum: 111111111011111111100n
console.log("Differens:", difference); // Output: Differens: -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: 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n

Vigtige overvejelser:

Sammenligningsoperatorer

Du kan bruge standard sammenligningsoperatorer (`==`, `!=`, `<`, `>`, `<=`, `>=`) til at sammenligne BigInt-værdier med andre BigInt-værdier eller endda med Number-værdier. Vær dog opmærksom på potentialet for type coercion (automatisk typekonvertering).

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

Bedste praksis: Brug streng lighed (`===`) og streng ulighed (`!==`) for at undgå uventet type coercion (automatisk typekonvertering), når du sammenligner BigInt- og Number-værdier.

Konvertering mellem BigInt og Number

Selvom direkte aritmetiske operationer mellem BigInt og Number ikke er tilladt, kan du konvertere mellem de to typer. Vær dog opmærksom på det potentielle tab af præcision, når du konverterer en BigInt til et Number, hvis BigInt-værdien overstiger `Number.MAX_SAFE_INTEGER`.

Eksempler:


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

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

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

Anvendelsestilfælde og eksempler

Kryptografi

Kryptografiske algoritmer er ofte afhængige af meget store primtal for sikkerhedens skyld. BigInt giver en måde at repræsentere og manipulere disse tal effektivt.


// Eksempel: Generering af et simpelt (usikkert) nøglepar
function generateKeyPair() {
  const p = 281n; // Et primtal
  const q = 283n; // Et andet primtal
  const n = p * q; // Modulus
  const totient = (p - 1n) * (q - 1n); // Eulers totientfunktion

  // Vælg et e (offentlig eksponent), så 1 < e < totient og gcd(e, totient) = 1
  const e = 17n;

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

Bemærk: Dette er et forenklet eksempel kun til demonstrationsformål. Kryptografi i den virkelige verden bruger meget større primtal og mere sofistikerede algoritmer.

Finansielle beregninger

Når man arbejder med store pengesummer, især i internationale transaktioner, er præcision afgørende. BigInt kan forhindre afrundingsfejl og sikre nøjagtige beregninger.


// Eksempel: Beregning af rentesregning
function calculateCompoundInterest(principal, rate, time) {
  const principalBigInt = BigInt(principal * 100); // Konverter til øre
  const rateBigInt = BigInt(rate * 10000);       // Konverter til ti-tusindedele af en 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% rentefod
const time = 10;     // 10 år

const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("Endeligt beløb:", finalAmount); // Output: Endeligt beløb: 1628894.6267774413 (cirka)

I dette eksempel konverterer vi hovedstolen og renten til BigInt-værdier for at undgå afrundingsfejl under beregningen. Resultatet konverteres derefter tilbage til et Number til visning.

Arbejde med store ID'er

I distribuerede systemer kan det være en udfordring at generere unikke ID'er på tværs af flere servere. Brug af BigInt giver dig mulighed for at oprette meget store ID'er, der med stor sandsynlighed ikke vil kollidere.


// Eksempel: Generering af et unikt ID baseret 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)); // Tilføj en smule tilfældighed

  // Kombiner værdierne for at oprette et unikt ID
  const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
  return uniqueId.toString(); // Returner som en streng for nem håndtering
}

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

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

BigInt og JSON

BigInt-værdier understøttes ikke native af JSON. Forsøg på at serialisere et JavaScript-objekt, der indeholder en BigInt, ved hjælp af `JSON.stringify()` vil resultere i en `TypeError`. For at håndtere BigInt-værdier, når du arbejder med JSON, har du et par muligheder:

  1. Konverter til streng: Konverter BigInt til en streng før serialisering. Dette er den mest almindelige og ligetil tilgang.
  2. Brugerdefineret serialisering/deserialisering: Brug en brugerdefineret serialiserings-/deserialiseringsfunktion til at håndtere BigInt-værdier.

Eksempler:

Konvertering til streng:


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

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

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

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

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

Brugerdefineret serialisering/deserialisering (ved hjælp af `replacer` og `reviver`):


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

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

console.log(jsonData);

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

console.log(parsedData.id);

Browserkompatibilitet

BigInt understøttes bredt i moderne browsere. Det er dog vigtigt at tjekke kompatibiliteten for ældre browsere eller miljøer. Du kan bruge et værktøj som Can I use til at verificere browserunderstøttelse. Hvis du skal understøtte ældre browsere, kan du overveje at bruge en polyfill, men vær opmærksom på, at polyfills kan påvirke ydeevnen.

Overvejelser om ydeevne

Selvom BigInt giver en kraftfuld måde at arbejde med store heltal på, er det vigtigt at være opmærksom på potentielle konsekvenser for ydeevnen.

Brug derfor kun BigInt, når det er nødvendigt, og optimer din kode for ydeevne, hvis du udfører et stort antal BigInt-operationer.

Konklusion

BigInt er en værdifuld tilføjelse til JavaScript, der gør det muligt for udviklere at håndtere stor heltalsaritmetik med præcision. Ved at forstå dens funktioner, begrænsninger og anvendelsestilfælde kan du udnytte BigInt til at bygge robuste og nøjagtige applikationer inden for forskellige domæner, herunder kryptografi, finansielle beregninger og videnskabelig databehandling. Husk at overveje browserkompatibilitet og konsekvenser for ydeevnen, når du bruger BigInt i dine projekter.

Yderligere udforskning

Denne guide giver et omfattende overblik over BigInt i JavaScript. Udforsk de linkede ressourcer for mere dybdegående information og avancerede teknikker.