En omfattande guide till JavaScripts BigInt-typ, som täcker dess funktioner, användning och tillämpningar för att hantera aritmetik med stora heltal. Lär dig övervinna JavaScripts begränsningar och utföra komplexa beräkningar med precision.
JavaScript BigInt: Bemästra aritmetik med stora heltal
JavaScript, trots att det är ett mångsidigt språk, har begränsningar när det gäller att hantera mycket stora heltal. Standardtypen `Number` kan endast representera heltal korrekt upp till en viss gräns, känd som `Number.MAX_SAFE_INTEGER`. Över denna gräns blir beräkningar oprecisa, vilket leder till oväntade resultat. Det är här BigInt
kommer till undsättning. Introducerat i ECMAScript 2020 är BigInt
ett inbyggt objekt som ger ett sätt att representera och manipulera heltal av godtycklig storlek, vilket överträffar begränsningarna hos standardtypen `Number`.
Förstå behovet av BigInt
Innan BigInt
var JavaScript-utvecklare tvungna att förlita sig på bibliotek eller anpassade implementeringar för att hantera beräkningar med stora heltal. Dessa lösningar medförde ofta prestandakostnader och ökad komplexitet. Införandet av BigInt
gav ett inbyggt och effektivt sätt att arbeta med stora heltal, vilket öppnade upp möjligheter för tillämpningar inom olika områden, inklusive:
- Kryptografi: Att säkert hantera stora primtal är avgörande för kryptografiska algoritmer.
- Finansiella beräkningar: Att noggrant representera stora penningvärden utan precisionsförlust.
- Vetenskapliga beräkningar: Att utföra komplexa beräkningar som involverar extremt stora eller små tal.
- Tidsstämplar med hög precision: Att representera tidsstämplar med nanosekundprecision.
- ID-generering: Att skapa unika och mycket stora identifierare.
Skapa BigInt-värden
Det finns två primära sätt att skapa BigInt
-värden i JavaScript:
- Använda `BigInt()`-konstruktorn: Denna konstruktor kan konvertera ett tal, en sträng eller ett booleskt värde till en
BigInt
. - Använda suffixet `n`: Att lägga till `n` i slutet av en heltalsliteral skapar en
BigInt
.
Exempel:
Använda `BigInt()`-konstruktorn:
const bigIntFromNumber = BigInt(12345678901234567890);
const bigIntFromString = BigInt("98765432109876543210");
const bigIntFromBoolean = BigInt(true); // Resulterar i 1n
const bigIntFromFalseBoolean = BigInt(false); // Resulterar i 0n
console.log(bigIntFromNumber); // Utskrift: 12345678901234567890n
console.log(bigIntFromString); // Utskrift: 98765432109876543210n
console.log(bigIntFromBoolean); // Utskrift: 1n
console.log(bigIntFromFalseBoolean); // Utskrift: 0n
Använda suffixet `n`:
const bigIntLiteral = 12345678901234567890n;
console.log(bigIntLiteral); // Utskrift: 12345678901234567890n
Viktigt att notera: Du kan inte direkt blanda BigInt
- och Number
-värden i aritmetiska operationer. Du måste explicit konvertera dem till samma typ innan du utför beräkningar. Ett försök att blanda dem direkt kommer att resultera i ett `TypeError`.
Aritmetiska operationer med BigInt
BigInt
stöder de flesta av de vanliga aritmetiska operatorerna, inklusive:
- Addition (`+`)
- Subtraktion (`-`)
- Multiplikation (`*`)
- Division (`/`)
- Rest (`%`)
- Exponentiering (`**`)
Exempel:
const a = 12345678901234567890n;
const b = 98765432109876543210n;
const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // Notera: Division avrundar mot noll
const remainder = a % 7n;
const power = a ** 3n; // Exponentiering fungerar som förväntat
console.log("Summa:", sum); // Utskrift: Summa: 111111111011111111100n
console.log("Differens:", difference); // Utskrift: Differens: -86419753208641975320n
console.log("Produkt:", product); // Utskrift: Produkt: 1219326311370217957951669538098765432100n
console.log("Kvot:", quotient); // Utskrift: Kvot: 6172839450617283945n
console.log("Rest:", remainder); // Utskrift: Rest: 5n
console.log("Potens:", power); // Utskrift: Potens: 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n
Viktiga överväganden:
- Division: Division med
BigInt
-värden avrundar mot noll. Detta innebär att decimaldelen av resultatet kastas bort. Om du behöver mer exakt division, överväg att använda bibliotek som stöder aritmetik med godtycklig precision. - Unär plusoperator (+): Den unära plusoperatorn (+) kan inte användas med
BigInt
-värden eftersom det skulle krocka med äldre asm.js-kod. Använd konverteringsfunktionen `Number()` för att konvertera en BigInt till ett Number om du behöver en numerisk representation (med förståelsen att du kan förlora precision). - Bitvisa operatorer:
BigInt
stöder också bitvisa operatorer som `&`, `|`, `^`, `~`, `<<` och `>>`. Dessa operatorer fungerar som förväntat på den binära representationen avBigInt
-värdena.
Jämförelseoperatorer
Du kan använda standardjämförelseoperatorer (`==`, `!=`, `<`, `>`, `<=`, `>=`) för att jämföra BigInt
-värden med andra BigInt
-värden eller till och med med Number
-värden. Var dock medveten om risken för typomvandling (type coercion).
Exempel:
const a = 10n;
const b = 20n;
const c = 10;
console.log(a == b); // Utskrift: false
console.log(a != b); // Utskrift: true
console.log(a < b); // Utskrift: true
console.log(a > b); // Utskrift: false
console.log(a <= b); // Utskrift: true
console.log(a >= b); // Utskrift: false
console.log(a == c); // Utskrift: true (typomvandling)
console.log(a === c); // Utskrift: false (ingen typomvandling)
Bästa praxis: Använd strikt likhet (`===`) och strikt olikhet (`!==`) för att undvika oväntad typomvandling när du jämför BigInt
- och Number
-värden.
Konvertera mellan BigInt och Number
Även om direkta aritmetiska operationer mellan BigInt
och Number
inte är tillåtna, kan du konvertera mellan de två typerna. Var dock medveten om den potentiella risken för precisionsförlust när du konverterar en BigInt
till en Number
om BigInt
-värdet överstiger `Number.MAX_SAFE_INTEGER`.
Exempel:
const bigIntValue = 9007199254740991n; // Number.MAX_SAFE_INTEGER
const numberValue = Number(bigIntValue); // Konverterar BigInt till Number
console.log(numberValue); // Utskrift: 9007199254740991
const largerBigIntValue = 9007199254740992n; // Överstiger Number.MAX_SAFE_INTEGER
const largerNumberValue = Number(largerBigIntValue);
console.log(largerNumberValue); // Utskrift: 9007199254740992 (kan vara oprecis)
const numberToBigInt = BigInt(12345); // Konverterar Number till BigInt
console.log(numberToBigInt); // Utskrift: 12345n
Användningsfall och exempel
Kryptografi
Kryptografiska algoritmer förlitar sig ofta på mycket stora primtal för säkerhet. BigInt
ger ett sätt att representera och manipulera dessa tal effektivt.
// Exempel: Generera ett enkelt (osäkert) nyckelpar
function generateKeyPair() {
const p = 281n; // Ett primtal
const q = 283n; // Ett annat primtal
const n = p * q; // Modulus
const totient = (p - 1n) * (q - 1n); // Eulers totientfunktion
// Välj ett e (offentlig exponent) så att 1 < e < totient och gcd(e, totient) = 1
const e = 17n;
// Beräkna d (privat exponent) så att (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 nyckel:", keyPair.publicKey);
console.log("Privat nyckel:", keyPair.privateKey);
Notera: Detta är ett förenklat exempel endast i demonstrationssyfte. Verklig kryptografi använder mycket större primtal och mer sofistikerade algoritmer.
Finansiella beräkningar
När man hanterar stora summor pengar, särskilt i internationella transaktioner, är precision avgörande. BigInt
kan förhindra avrundningsfel och säkerställa exakta beräkningar.
// Exempel: Beräkna ränta-på-ränta
function calculateCompoundInterest(principal, rate, time) {
const principalBigInt = BigInt(principal * 100); // Konvertera till cent
const rateBigInt = BigInt(rate * 10000); // Konvertera till tiotusendelar av 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% ränta
const time = 10; // 10 år
const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("Slutligt belopp:", finalAmount); // Utskrift: Slutligt belopp: 1628894.6267774413 (ungefär)
I detta exempel konverterar vi kapitalbeloppet och räntan till BigInt
-värden för att undvika avrundningsfel under beräkningen. Resultatet konverteras sedan tillbaka till ett Number
för visning.
Arbeta med stora ID:n
I distribuerade system kan det vara en utmaning att generera unika ID:n över flera servrar. Genom att använda BigInt
kan du skapa mycket stora ID:n som sannolikt inte kommer att kollidera.
// Exempel: Generera ett unikt ID baserat på tidsstämpel och server-ID
function generateUniqueId(serverId) {
const timestamp = BigInt(Date.now());
const serverIdBigInt = BigInt(serverId);
const random = BigInt(Math.floor(Math.random() * 1000)); // Lägg till lite slumpmässighet
// Kombinera värdena för att skapa ett unikt ID
const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
return uniqueId.toString(); // Returnera som en sträng för enkel hantering
}
const serverId = 123; // Exempel på server-ID
const id1 = generateUniqueId(serverId);
const id2 = generateUniqueId(serverId);
console.log("Unikt ID 1:", id1);
console.log("Unikt ID 2:", id2);
BigInt och JSON
BigInt
-värden stöds inte inbyggt av JSON. Ett försök att serialisera ett JavaScript-objekt som innehåller en BigInt
med `JSON.stringify()` kommer att resultera i ett `TypeError`. För att hantera BigInt
-värden när du arbetar med JSON har du ett par alternativ:
- Konvertera till sträng: Konvertera
BigInt
till en sträng innan serialisering. Detta är den vanligaste och mest raka metoden. - Anpassad serialisering/deserialisering: Använd en anpassad funktion för serialisering och deserialisering för att hantera
BigInt
-värden.
Exempel:
Konvertera till sträng:
const data = {
id: 12345678901234567890n,
name: "Example Data",
};
// Konvertera BigInt till sträng innan serialisering
data.id = data.id.toString();
const jsonData = JSON.stringify(data);
console.log(jsonData); // Utskrift: {"id":"12345678901234567890","name":"Example Data"}
// Vid deserialisering måste du konvertera strängen tillbaka till en BigInt
const parsedData = JSON.parse(jsonData, (key, value) => {
if (key === "id") {
return BigInt(value);
}
return value;
});
console.log(parsedData.id); // Utskrift: 12345678901234567890n
Anpassad serialisering/deserialisering (med `replacer` och `reviver`):
const data = {
id: 12345678901234567890n,
name: "Example Data",
};
// Anpassad serialisering
const jsonData = JSON.stringify(data, (key, value) => {
if (typeof value === 'bigint') {
return value.toString();
} else {
return value;
}
});
console.log(jsonData);
// Anpassad deserialisering
const parsedData = JSON.parse(jsonData, (key, value) => {
if (typeof value === 'string' && /^[0-9]+$/.test(value)) { // kontrollera om det är ett tal och en sträng
try {
return BigInt(value);
} catch(e) {
return value;
}
}
return value;
});
console.log(parsedData.id);
Webbläsarkompatibilitet
BigInt
har brett stöd i moderna webbläsare. Det är dock viktigt att kontrollera kompatibiliteten för äldre webbläsare eller miljöer. Du kan använda ett verktyg som Can I use för att verifiera webbläsarstöd. Om du behöver stödja äldre webbläsare kan du överväga att använda en polyfill, men var medveten om att polyfills kan påverka prestandan.
Prestandaöverväganden
Även om BigInt
erbjuder ett kraftfullt sätt att arbeta med stora heltal, är det viktigt att vara medveten om potentiella prestandakonsekvenser.
BigInt
-operationer kan vara långsammare än vanligaNumber
-operationer.- Konvertering mellan
BigInt
ochNumber
kan också medföra en prestandakostnad.
Använd därför BigInt
endast när det är nödvändigt, och optimera din kod för prestanda om du utför ett stort antal BigInt
-operationer.
Slutsats
BigInt
är ett värdefullt tillskott till JavaScript som gör det möjligt för utvecklare att hantera aritmetik med stora heltal med precision. Genom att förstå dess funktioner, begränsningar och användningsfall kan du utnyttja BigInt
för att bygga robusta och exakta applikationer inom olika områden, inklusive kryptografi, finansiella beräkningar och vetenskaplig databehandling. Kom ihåg att ta hänsyn till webbläsarkompatibilitet och prestandakonsekvenser när du använder BigInt
i dina projekt.
Vidare läsning
- Mozilla Developer Network (MDN) - BigInt
- V8 Blog - BigInt: Arbitrary-Precision Integers in JavaScript
Denna guide ger en omfattande översikt av BigInt
i JavaScript. Utforska de länkade resurserna för mer djupgående information och avancerade tekniker.