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:
- Kryptografi: Sikker håndtering av store primtall er avgjørende for kryptografiske algoritmer.
- Finansielle beregninger: Nøyaktig representasjon av store pengeverdier uten tap av presisjon.
- Vitenskapelig databehandling: Utføre komplekse beregninger som involverer ekstremt store eller små tall.
- Høypresisjons tidsstempler: Representere tidsstempler med nanosekund-presisjon.
- ID-generering: Skape unike og veldig store identifikatorer.
Å skape BigInt-verdier
Det er to primære måter å skape BigInt
-verdier i JavaScript:
- Bruke `BigInt()`-konstruktøren: Denne konstruktøren kan konvertere et tall, en streng eller en boolsk verdi til en
BigInt
. - 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:
- Addisjon (`+`)
- Subtraksjon (`-`)
- Multiplikasjon (`*`)
- Divisjon (`/`)
- Rest (`%`)
- Eksponentiering (`**`)
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:
- Divisjon: Divisjon med
BigInt
-verdier avkorter mot null. Dette betyr at desimaldelen av resultatet forkastes. Hvis du trenger mer presis divisjon, bør du vurdere å bruke biblioteker som støtter vilkårlig-presisjonsaritmetikk. - Unær plussoperator (+): Den unære plussoperatoren (+) kan ikke brukes med
BigInt
-verdier fordi det ville komme i konflikt med eldre asm.js-kode. Bruk konverteringsfunksjonen `Number()` for å konvertere en BigInt til et Number hvis du trenger en numerisk representasjon (med forståelse for at du kan miste presisjon). - Bitvise operatorer:
BigInt
støtter også bitvise operatorer som `&`, `|`, `^`, `~`, `<<` og `>>`. Disse operatorene fungerer som forventet på den binære representasjonen avBigInt
-verdiene.
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:
- Konverter til streng: Konverter
BigInt
til en streng før serialisering. Dette er den vanligste og enkleste tilnærmingen. - 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.
BigInt
-operasjoner kan være tregere enn standardNumber
-operasjoner.- Konvertering mellom
BigInt
ogNumber
kan også medføre ekstra overhead.
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
- Mozilla Developer Network (MDN) - BigInt
- V8-bloggen - BigInt: Arbitrary-Precision Integers in JavaScript
Denne guiden gir en omfattende oversikt over BigInt
i JavaScript. Utforsk de lenkede ressursene for mer dyptgående informasjon og avanserte teknikker.