Išsamus JavaScript BigInt tipo vadovas, apimantis jo funkcijas, naudojimą ir pritaikymą dirbant su didelių sveikųjų skaičių aritmetika. Sužinokite, kaip įveikti JavaScript apribojimus ir tiksliai atlikti sudėtingus skaičiavimus.
JavaScript BigInt: Didelių sveikųjų skaičių aritmetikos įvaldymas
Nors JavaScript yra universali kalba, ji turi apribojimų dirbant su labai dideliais sveikaisiais skaičiais. Standartinis `Number` tipas gali tiksliai atvaizduoti sveikuosius skaičius tik iki tam tikros ribos, žinomos kaip `Number.MAX_SAFE_INTEGER`. Viršijus šią ribą, skaičiavimai tampa netikslūs, todėl gaunami netikėti rezultatai. Būtent čia į pagalbą ateina BigInt
. Pristatytas ECMAScript 2020, BigInt
yra integruotas objektas, suteikiantis būdą atvaizduoti ir manipuliuoti savavališko dydžio sveikaisiais skaičiais, viršijančiais standartinio `Number` tipo apribojimus.
BigInt poreikio supratimas
Prieš atsirandant BigInt
, JavaScript programuotojai turėjo pasikliauti bibliotekomis arba individualiais sprendimais, kad galėtų atlikti didelių sveikųjų skaičių skaičiavimus. Šie sprendimai dažnai turėjo neigiamą poveikį našumui ir didino sudėtingumą. BigInt
įvedimas suteikė natūralų ir efektyvų būdą dirbti su dideliais sveikaisiais skaičiais, atveriant galimybes pritaikymui įvairiose srityse, įskaitant:
- Kriptografija: Saugus darbas su dideliais pirminiais skaičiais yra labai svarbus kriptografiniams algoritmams.
- Finansiniai skaičiavimai: Tikslus didelių piniginių verčių atvaizdavimas neprarandant tikslumo.
- Moksliniai skaičiavimai: Sudėtingų skaičiavimų, apimančių itin didelius ar mažus skaičius, atlikimas.
- Aukšto tikslumo laiko žymos: Laiko žymų atvaizdavimas nanosekundžių tikslumu.
- ID generavimas: Unikalių ir labai didelių identifikatorių kūrimas.
BigInt reikšmių kūrimas
Yra du pagrindiniai būdai sukurti BigInt
reikšmes JavaScript:
- Naudojant `BigInt()` konstruktorių: Šis konstruktorius gali konvertuoti skaičių, eilutę ar loginę reikšmę į
BigInt
. - Naudojant `n` priesagą: Pridėjus `n` prie sveikojo skaičiaus literalo, sukuriamas
BigInt
.
Pavyzdžiai:
Naudojant `BigInt()` konstruktorių:
const bigIntFromNumber = BigInt(12345678901234567890);
const bigIntFromString = BigInt("98765432109876543210");
const bigIntFromBoolean = BigInt(true); // Rezultatas 1n
const bigIntFromFalseBoolean = BigInt(false); // Rezultatas 0n
console.log(bigIntFromNumber); // Išvestis: 12345678901234567890n
console.log(bigIntFromString); // Išvestis: 98765432109876543210n
console.log(bigIntFromBoolean); // Išvestis: 1n
console.log(bigIntFromFalseBoolean); // Išvestis: 0n
Naudojant `n` priesagą:
const bigIntLiteral = 12345678901234567890n;
console.log(bigIntLiteral); // Išvestis: 12345678901234567890n
Svarbi pastaba: Jūs negalite tiesiogiai maišyti BigInt
ir Number
reikšmių aritmetinėse operacijose. Prieš atliekant skaičiavimus, juos reikia aiškiai konvertuoti į tą patį tipą. Bandant juos maišyti tiesiogiai, gausite `TypeError` klaidą.
BigInt aritmetinės operacijos
BigInt
palaiko daugumą standartinių aritmetinių operatorių, įskaitant:
- Sudėtis (`+`)
- Atimtis (`-`)
- Daugyba (`*`)
- Dalyba (`/`)
- Liekana (`%`)
- Kėlimas laipsniu (`**`)
Pavyzdžiai:
const a = 12345678901234567890n;
const b = 98765432109876543210n;
const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // Pastaba: Dalyba apvalina link nulio
const remainder = a % 7n;
const power = a ** 3n; // Kėlimas laipsniu veikia kaip tikėtasi
console.log("Suma:", sum); // Išvestis: Suma: 111111111011111111100n
console.log("Skirtumas:", difference); // Išvestis: Skirtumas: -86419753208641975320n
console.log("Sandauga:", product); // Išvestis: Sandauga: 1219326311370217957951669538098765432100n
console.log("Dalmuo:", quotient); // Išvestis: Dalmuo: 6172839450617283945n
console.log("Liekana:", remainder); // Išvestis: Liekana: 5n
console.log("Laipsnis:", power); // Išvestis: Laipsnis: 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n
Svarbūs aspektai:
- Dalyba: Dalyba su
BigInt
reikšmėmis apvalina link nulio. Tai reiškia, kad dešimtainė rezultato dalis yra atmetama. Jei jums reikia tikslesnės dalybos, apsvarstykite galimybę naudoti bibliotekas, kurios palaiko savavališko tikslumo aritmetiką. - Unarinis pliuso operatorius (+): Unarinis pliuso operatorius (+) negali būti naudojamas su
BigInt
reikšmėmis, nes tai sukeltų konfliktą su senuoju asm.js kodu. Naudokite `Number()` konvertavimo funkciją, kad konvertuotumėte BigInt į Number, jei jums reikia skaitinio atvaizdavimo (suprantant, kad galite prarasti tikslumą). - Bitų operacijos:
BigInt
taip pat palaiko bitų operacijas, tokias kaip `&`, `|`, `^`, `~`, `<<` ir `>>`. Šie operatoriai veikia kaip tikėtasi suBigInt
reikšmių dvinariu atvaizdavimu.
Palyginimo operatoriai
Galite naudoti standartinius palyginimo operatorius (`==`, `!=`, `<`, `>`, `<=`, `>=`), kad palygintumėte BigInt
reikšmes su kitomis BigInt
reikšmėmis ar net su Number
reikšmėmis. Tačiau būkite atidūs dėl galimo tipų privertimo (type coercion).
Pavyzdžiai:
const a = 10n;
const b = 20n;
const c = 10;
console.log(a == b); // Išvestis: false
console.log(a != b); // Išvestis: true
console.log(a < b); // Išvestis: true
console.log(a > b); // Išvestis: false
console.log(a <= b); // Išvestis: true
console.log(a >= b); // Išvestis: false
console.log(a == c); // Išvestis: true (tipų privertimas)
console.log(a === c); // Išvestis: false (nėra tipų privertimo)
Geroji praktika: Naudokite griežtą lygybę (`===`) ir griežtą nelygybę (`!==`), kad išvengtumėte netikėto tipų privertimo, lygindami BigInt
ir Number
reikšmes.
Konvertavimas tarp BigInt ir Number
Nors tiesioginės aritmetinės operacijos tarp BigInt
ir Number
yra neleidžiamos, galite konvertuoti tarp šių dviejų tipų. Tačiau atminkite, kad konvertuojant BigInt
į Number
gali būti prarastas tikslumas, jei BigInt
reikšmė viršija `Number.MAX_SAFE_INTEGER`.
Pavyzdžiai:
const bigIntValue = 9007199254740991n; // Number.MAX_SAFE_INTEGER
const numberValue = Number(bigIntValue); // Konvertuojama BigInt į Number
console.log(numberValue); // Išvestis: 9007199254740991
const largerBigIntValue = 9007199254740992n; // Viršija Number.MAX_SAFE_INTEGER
const largerNumberValue = Number(largerBigIntValue);
console.log(largerNumberValue); // Išvestis: 9007199254740992 (gali būti netikslus)
const numberToBigInt = BigInt(12345); // Konvertuojama Number į BigInt
console.log(numberToBigInt); // Išvestis: 12345n
Panaudojimo atvejai ir pavyzdžiai
Kriptografija
Kriptografiniai algoritmai dažnai naudoja labai didelius pirminius skaičius saugumui užtikrinti. BigInt
suteikia būdą efektyviai atvaizduoti ir manipuliuoti šiais skaičiais.
// Pavyzdys: Paprastos (nesaugios) raktų poros generavimas
function generateKeyPair() {
const p = 281n; // Pirminis skaičius
const q = 283n; // Kitas pirminis skaičius
const n = p * q; // Modulis
const totient = (p - 1n) * (q - 1n); // Eulerio totient funkcija
// Pasirinkite e (viešąjį rodiklį) tokį, kad 1 < e < totient ir gcd(e, totient) = 1
const e = 17n;
// Apskaičiuokite d (privatųjį rodiklį) tokį, kad (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("Viešasis raktas:", keyPair.publicKey);
console.log("Privatus raktas:", keyPair.privateKey);
Pastaba: Tai yra supaprastintas pavyzdys, skirtas tik demonstravimo tikslams. Realiame pasaulyje kriptografija naudoja daug didesnius pirminius skaičius ir sudėtingesnius algoritmus.
Finansiniai skaičiavimai
Dirbant su didelėmis pinigų sumomis, ypač tarptautiniuose sandoriuose, tikslumas yra labai svarbus. BigInt
gali padėti išvengti apvalinimo klaidų ir užtikrinti tikslius skaičiavimus.
// Pavyzdys: Sudėtinių palūkanų skaičiavimas
function calculateCompoundInterest(principal, rate, time) {
const principalBigInt = BigInt(principal * 100); // Konvertuoti į centus
const rateBigInt = BigInt(rate * 10000); // Konvertuoti į dešimt tūkstantąsias procento dalis
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% palūkanų norma
const time = 10; // 10 metų
const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("Galutinė suma:", finalAmount); // Išvestis: Galutinė suma: 1628894.6267774413 (apytiksliai)
Šiame pavyzdyje mes konvertuojame pradinę sumą ir palūkanų normą į BigInt
reikšmes, kad išvengtume apvalinimo klaidų skaičiavimo metu. Rezultatas tada konvertuojamas atgal į Number
, kad būtų parodytas.
Darbas su dideliais ID
Paskirstytose sistemose unikalių ID generavimas keliuose serveriuose gali būti sudėtingas. Naudojant BigInt
galima sukurti labai didelius ID, kurių susidūrimo tikimybė yra maža.
// Pavyzdys: Unikalaus ID generavimas pagal laiko žymą ir serverio ID
function generateUniqueId(serverId) {
const timestamp = BigInt(Date.now());
const serverIdBigInt = BigInt(serverId);
const random = BigInt(Math.floor(Math.random() * 1000)); // Pridėti šiek tiek atsitiktinumo
// Sujungti reikšmes, kad būtų sukurtas unikalus ID
const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
return uniqueId.toString(); // Grąžinti kaip eilutę, kad būtų lengviau apdoroti
}
const serverId = 123; // Pavyzdinis serverio ID
const id1 = generateUniqueId(serverId);
const id2 = generateUniqueId(serverId);
console.log("Unikalus ID 1:", id1);
console.log("Unikalus ID 2:", id2);
BigInt ir JSON
JSON natūraliai nepalaiko BigInt
reikšmių. Bandant serializuoti JavaScript objektą, kuriame yra BigInt
, naudojant `JSON.stringify()`, gausite `TypeError` klaidą. Norėdami apdoroti BigInt
reikšmes dirbant su JSON, turite keletą galimybių:
- Konvertuoti į eilutę: Prieš serializuojant, konvertuokite
BigInt
į eilutę. Tai yra labiausiai paplitęs ir tiesiausias būdas. - Individualus serializavimas/deserializavimas: Naudokite individualią serializavimo/deserializavimo funkciją, kad apdorotumėte
BigInt
reikšmes.
Pavyzdžiai:
Konvertavimas į eilutę:
const data = {
id: 12345678901234567890n,
name: "Example Data",
};
// Konvertuoti BigInt į eilutę prieš serializuojant
data.id = data.id.toString();
const jsonData = JSON.stringify(data);
console.log(jsonData); // Išvestis: {"id":"12345678901234567890","name":"Example Data"}
// Deserializuojant, reikės konvertuoti eilutę atgal į BigInt
const parsedData = JSON.parse(jsonData, (key, value) => {
if (key === "id") {
return BigInt(value);
}
return value;
});
console.log(parsedData.id); // Išvestis: 12345678901234567890n
Individualus serializavimas/deserializavimas (naudojant `replacer` ir `reviver`):
const data = {
id: 12345678901234567890n,
name: "Example Data",
};
// Individualus serializavimas
const jsonData = JSON.stringify(data, (key, value) => {
if (typeof value === 'bigint') {
return value.toString();
} else {
return value;
}
});
console.log(jsonData);
// Individualus deserializavimas
const parsedData = JSON.parse(jsonData, (key, value) => {
if (typeof value === 'string' && /^[0-9]+$/.test(value)) { //patikrinti, ar tai yra skaičius ir eilutė
try {
return BigInt(value);
} catch(e) {
return value;
}
}
return value;
});
console.log(parsedData.id);
Naršyklių suderinamumas
BigInt
yra plačiai palaikomas šiuolaikinėse naršyklėse. Tačiau būtina patikrinti suderinamumą su senesnėmis naršyklėmis ar aplinkomis. Galite naudoti įrankį, pvz., Can I use, kad patikrintumėte naršyklių palaikymą. Jei reikia palaikyti senesnes naršykles, galite apsvarstyti galimybę naudoti „polyfill“, tačiau atminkite, kad „polyfills“ gali paveikti našumą.
Našumo aspektai
Nors BigInt
suteikia galingą būdą dirbti su dideliais sveikaisiais skaičiais, svarbu žinoti apie galimą poveikį našumui.
BigInt
operacijos gali būti lėtesnės nei standartinėsNumber
operacijos.- Konvertavimas tarp
BigInt
irNumber
taip pat gali sukelti papildomų sąnaudų.
Todėl naudokite BigInt
tik tada, kai tai būtina, ir optimizuokite savo kodą našumui, jei atliekate daug BigInt
operacijų.
Išvada
BigInt
yra vertingas JavaScript papildymas, leidžiantis programuotojams tiksliai atlikti didelių sveikųjų skaičių aritmetiką. Suprasdami jo ypatybes, apribojimus ir panaudojimo atvejus, galite pasinaudoti BigInt
kurdami patikimas ir tikslias programas įvairiose srityse, įskaitant kriptografiją, finansinius skaičiavimus ir mokslinius skaičiavimus. Nepamirškite atsižvelgti į naršyklių suderinamumą ir našumo pasekmes, kai naudojate BigInt
savo projektuose.
Tolimesnis tyrinėjimas
- Mozilla Developer Network (MDN) - BigInt
- V8 Blogas - BigInt: Savavališko tikslumo sveikieji skaičiai JavaScript
Šis vadovas pateikia išsamią BigInt
apžvalgą JavaScript kalboje. Išsamesnės informacijos ir pažangesnių technikų ieškokite nurodytuose šaltiniuose.