Kattava opas JavaScriptin BigInt-tyyppiin, joka kattaa sen ominaisuudet, käytön ja sovellukset suurten kokonaislukujen aritmetiikassa. Opi ylittämään JavaScriptin rajoitukset ja suorittamaan monimutkaisia laskelmia tarkasti.
JavaScript BigInt: Suurten kokonaislukujen aritmetiikan hallinta
Vaikka JavaScript on monipuolinen kieli, sillä on rajoituksia erittäin suurten kokonaislukujen käsittelyssä. Standardi `Number`-tyyppi voi esittää kokonaislukuja tarkasti vain tiettyyn rajaan asti, joka tunnetaan nimellä `Number.MAX_SAFE_INTEGER`. Tämän rajan ylittyessä laskelmista tulee epätarkkoja, mikä johtaa odottamattomiin tuloksiin. Tässä kohtaa BigInt
tulee apuun. ECMAScript 2020:ssa esitelty BigInt
on sisäänrakennettu olio, joka tarjoaa tavan esittää ja käsitellä mielivaltaisen kokoisia kokonaislukuja, ylittäen standardin `Number`-tyypin rajoitukset.
Miksi BigInt on tarpeellinen?
Ennen BigInt
-tyyppiä JavaScript-kehittäjien oli turvauduttava kirjastoihin tai omiin toteutuksiin suurten kokonaislukujen laskutoimitusten käsittelyssä. Nämä ratkaisut toivat usein mukanaan suorituskykyyn liittyviä yleiskustannuksia ja lisäsivät monimutkaisuutta. BigInt
-tyypin käyttöönotto tarjosi natiivin ja tehokkaan tavan työskennellä suurten kokonaislukujen kanssa, avaten mahdollisuuksia sovelluksille eri aloilla, mukaan lukien:
- Kryptografia: Suurten alkulukujen turvallinen käsittely on ratkaisevan tärkeää kryptografisille algoritmeille.
- Talouslaskelmat: Suurten rahasummien tarkka esittäminen ilman tarkkuuden menetystä.
- Tieteellinen laskenta: Monimutkaisten laskutoimitusten suorittaminen, jotka sisältävät erittäin suuria tai pieniä lukuja.
- Korkean tarkkuuden aikaleimat: Aikaleimojen esittäminen nanosekunnin tarkkuudella.
- Tunnisteiden luonti: Ainutlaatuisten ja erittäin suurten tunnisteiden luominen.
BigInt-arvojen luominen
JavaScriptissä on kaksi pääasiallista tapaa luoda BigInt
-arvoja:
- Käyttämällä `BigInt()`-konstruktoria: Tämä konstruktori voi muuntaa numeron, merkkijonon tai boolean-arvon
BigInt
-tyypiksi. - Käyttämällä `n`-liitettä: `n`-liitteen lisääminen kokonaislukulitteraalin perään luo
BigInt
-arvon.
Esimerkkejä:
Käyttämällä `BigInt()`-konstruktoria:
const bigIntFromNumber = BigInt(12345678901234567890);
const bigIntFromString = BigInt("98765432109876543210");
const bigIntFromBoolean = BigInt(true); // Tulos on 1n
const bigIntFromFalseBoolean = BigInt(false); // Tulos on 0n
console.log(bigIntFromNumber); // Tuloste: 12345678901234567890n
console.log(bigIntFromString); // Tuloste: 98765432109876543210n
console.log(bigIntFromBoolean); // Tuloste: 1n
console.log(bigIntFromFalseBoolean); // Tuloste: 0n
Käyttämällä `n`-liitettä:
const bigIntLiteral = 12345678901234567890n;
console.log(bigIntLiteral); // Tuloste: 12345678901234567890n
Tärkeä huomautus: Et voi sekoittaa suoraan BigInt
- ja Number
-arvoja aritmeettisissa operaatioissa. Sinun on eksplisiittisesti muunnettava ne samaan tyyppiin ennen laskutoimitusten suorittamista. Niiden sekoittaminen suoraan johtaa `TypeError`-virheeseen.
BigInt-aritmetiikkaoperaatiot
BigInt
tukee useimpia standardeja aritmeettisia operaattoreita, kuten:
- Yhteenlasku (`+`)
- Vähennyslasku (`-`)
- Kertolasku (`*`)
- Jakolasku (`/`)
- Jakojäännös (`%`)
- Potenssiin korotus (`**`)
Esimerkkejä:
const a = 12345678901234567890n;
const b = 98765432109876543210n;
const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // Huom: Jakolasku katkaisee kohti nollaa
const remainder = a % 7n;
const power = a ** 3n; // Potenssiin korotus toimii odotetusti
console.log("Summa:", sum); // Tuloste: Summa: 111111111011111111100n
console.log("Erotus:", difference); // Tuloste: Erotus: -86419753208641975320n
console.log("Tulo:", product); // Tuloste: Tulo: 1219326311370217957951669538098765432100n
console.log("Osamäärä:", quotient); // Tuloste: Osamäärä: 6172839450617283945n
console.log("Jakojäännös:", remainder); // Tuloste: Jakojäännös: 5n
console.log("Potenssi:", power); // Tuloste: Potenssi: 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n
Tärkeitä huomioita:
- Jakolasku: Jakolasku
BigInt
-arvoilla katkaisee tuloksen kohti nollaa. Tämä tarkoittaa, että tuloksen desimaaliosa hylätään. Jos tarvitset tarkempaa jakolaskua, harkitse kirjastojen käyttöä, jotka tukevat mielivaltaisen tarkkuuden aritmetiikkaa. - Unaarinen plus-operaattori (+): Unaarista plus-operaattoria (+) ei voi käyttää
BigInt
-arvojen kanssa, koska se olisi ristiriidassa vanhan asm.js-koodin kanssa. Käytä `Number()`-muunnosfunktiota muuntaaksesi BigInt-arvon Number-tyypiksi, jos tarvitset numeerisen esitysmuodon (ymmärtäen, että saatat menettää tarkkuutta). - Bitti-operaattorit:
BigInt
tukee myös bitti-operaattoreita, kuten `&`, `|`, `^`, `~`, `<<` ja `>>`. Nämä operaattorit toimivat odotetustiBigInt
-arvojen binääriesityksillä.
Vertailuoperaattorit
Voit käyttää standardeja vertailuoperaattoreita (`==`, `!=`, `<`, `>`, `<=`, `>=`) vertaillaksesi BigInt
-arvoja muihin BigInt
-arvoihin tai jopa Number
-arvoihin. Ole kuitenkin tietoinen mahdollisesta tyyppimuunnoksesta (type coercion).
Esimerkkejä:
const a = 10n;
const b = 20n;
const c = 10;
console.log(a == b); // Tuloste: false
console.log(a != b); // Tuloste: true
console.log(a < b); // Tuloste: true
console.log(a > b); // Tuloste: false
console.log(a <= b); // Tuloste: true
console.log(a >= b); // Tuloste: false
console.log(a == c); // Tuloste: true (tyyppimuunnos)
console.log(a === c); // Tuloste: false (ei tyyppimuunnosta)
Paras käytäntö: Käytä tiukkaa yhtäsuuruutta (`===`) ja tiukkaa erisuuruutta (`!==`) välttääksesi odottamattomia tyyppimuunnoksia vertaillessasi BigInt
- ja Number
-arvoja.
Muunnokset BigIntin ja Numberin välillä
Vaikka suorat aritmeettiset operaatiot BigInt
- ja Number
-tyyppien välillä eivät ole sallittuja, voit muuntaa arvoja näiden kahden tyypin välillä. Ole kuitenkin tietoinen mahdollisesta tarkkuuden menetyksestä, kun muunnat BigInt
-arvon Number
-tyypiksi, jos BigInt
-arvo ylittää `Number.MAX_SAFE_INTEGER`.
Esimerkkejä:
const bigIntValue = 9007199254740991n; // Number.MAX_SAFE_INTEGER
const numberValue = Number(bigIntValue); // Muunnetaan BigInt Number-tyypiksi
console.log(numberValue); // Tuloste: 9007199254740991
const largerBigIntValue = 9007199254740992n; // Ylittää Number.MAX_SAFE_INTEGER
const largerNumberValue = Number(largerBigIntValue);
console.log(largerNumberValue); // Tuloste: 9007199254740992 (voi olla epätarkka)
const numberToBigInt = BigInt(12345); // Muunnetaan Number BigInt-tyypiksi
console.log(numberToBigInt); // Tuloste: 12345n
Käyttötapauksia ja esimerkkejä
Kryptografia
Kryptografiset algoritmit perustuvat usein erittäin suuriin alkulukuihin turvallisuuden takaamiseksi. BigInt
tarjoaa tavan esittää ja käsitellä näitä lukuja tehokkaasti.
// Esimerkki: Yksinkertaisen (turvattoman) avainparin luominen
function generateKeyPair() {
const p = 281n; // Alkuluku
const q = 283n; // Toinen alkuluku
const n = p * q; // Modulus
const totient = (p - 1n) * (q - 1n); // Eulerin totienttifunktio
// Valitse e (julkinen eksponentti) siten, että 1 < e < totient ja syt(e, totient) = 1
const e = 17n;
// Laske d (yksityinen eksponentti) siten, että (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("Julkinen avain:", keyPair.publicKey);
console.log("Yksityinen avain:", keyPair.privateKey);
Huomautus: Tämä on yksinkertaistettu esimerkki vain havainnollistamistarkoituksessa. Oikeassa kryptografiassa käytetään paljon suurempia alkulukuja ja kehittyneempiä algoritmeja.
Talouslaskelmat
Kun käsitellään suuria rahasummia, erityisesti kansainvälisissä transaktioissa, tarkkuus on kriittistä. BigInt
voi estää pyöristysvirheitä ja varmistaa tarkat laskelmat.
// Esimerkki: Korkoa korolle -laskelma
function calculateCompoundInterest(principal, rate, time) {
const principalBigInt = BigInt(principal * 100); // Muunna senteiksi
const rateBigInt = BigInt(rate * 10000); // Muunna prosentin kymmenestuhannesosiksi
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 dollaria
const rate = 0.05; // 5% korko
const time = 10; // 10 vuotta
const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("Lopullinen summa:", finalAmount); // Tuloste: Lopullinen summa: 1628894.6267774413 (suunnilleen)
Tässä esimerkissä muunnamme pääoman ja koron BigInt
-arvoiksi välttääksemme pyöristysvirheitä laskennan aikana. Tulos muunnetaan sitten takaisin Number
-tyypiksi näytettäväksi.
Suurten tunnisteiden käsittely
Hajautetuissa järjestelmissä ainutlaatuisten tunnisteiden luominen useilla palvelimilla voi olla haastavaa. BigInt
-tyypin avulla voit luoda erittäin suuria tunnisteita, jotka eivät todennäköisesti törmää toisiinsa.
// Esimerkki: Ainutlaatuisen tunnisteen luominen aikaleiman ja palvelintunnisteen perusteella
function generateUniqueId(serverId) {
const timestamp = BigInt(Date.now());
const serverIdBigInt = BigInt(serverId);
const random = BigInt(Math.floor(Math.random() * 1000)); // Lisätään hieman satunnaisuutta
// Yhdistetään arvot ainutlaatuisen tunnisteen luomiseksi
const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
return uniqueId.toString(); // Palautetaan merkkijonona helppoa käsittelyä varten
}
const serverId = 123; // Esimerkki palvelintunnisteesta
const id1 = generateUniqueId(serverId);
const id2 = generateUniqueId(serverId);
console.log("Ainutlaatuinen ID 1:", id1);
console.log("Ainutlaatuinen ID 2:", id2);
BigInt ja JSON
JSON ei tue BigInt
-arvoja natiivisti. Jos yrität serialisoida JavaScript-objektia, joka sisältää BigInt
-arvon, käyttämällä `JSON.stringify()`-funktiota, tuloksena on `TypeError`. BigInt
-arvojen käsittelyyn JSON-kontekstissa on pari vaihtoehtoa:
- Muunna merkkijonoksi: Muunna
BigInt
merkkijonoksi ennen serialisointia. Tämä on yleisin ja suoraviivaisin lähestymistapa. - Mukautettu serialisointi/deserialisointi: Käytä mukautettua serialisointi-/deserialisointifunktiota
BigInt
-arvojen käsittelyyn.
Esimerkkejä:
Muunna merkkijonoksi:
const data = {
id: 12345678901234567890n,
name: "Esimerkkidata",
};
// Muunna BigInt merkkijonoksi ennen serialisointia
data.id = data.id.toString();
const jsonData = JSON.stringify(data);
console.log(jsonData); // Tuloste: {"id":"12345678901234567890","name":"Esimerkkidata"}
// Deserialisoinnin yhteydessä sinun on muunnettava merkkijono takaisin BigInt-tyypiksi
const parsedData = JSON.parse(jsonData, (key, value) => {
if (key === "id") {
return BigInt(value);
}
return value;
});
console.log(parsedData.id); // Tuloste: 12345678901234567890n
Mukautettu serialisointi/deserialisointi (käyttäen `replacer`- ja `reviver`-funktioita):
const data = {
id: 12345678901234567890n,
name: "Esimerkkidata",
};
// Mukautettu serialisointi
const jsonData = JSON.stringify(data, (key, value) => {
if (typeof value === 'bigint') {
return value.toString();
} else {
return value;
}
});
console.log(jsonData);
// Mukautettu deserialisointi
const parsedData = JSON.parse(jsonData, (key, value) => {
if (typeof value === 'string' && /^[0-9]+$/.test(value)) { // tarkista onko se numero ja merkkijono
try {
return BigInt(value);
} catch(e) {
return value;
}
}
return value;
});
console.log(parsedData.id);
Selainyhteensopivuus
BigInt
on laajalti tuettu moderneissa selaimissa. On kuitenkin tärkeää tarkistaa yhteensopivuus vanhempien selainten tai ympäristöjen kanssa. Voit käyttää työkalua, kuten Can I use, tarkistaaksesi selainten tuen. Jos sinun on tuettava vanhempia selaimia, voit harkita polyfillin käyttöä, mutta ole tietoinen siitä, että polyfillit voivat vaikuttaa suorituskykyyn.
Suorituskykyyn liittyviä huomioita
Vaikka BigInt
tarjoaa tehokkaan tavan työskennellä suurten kokonaislukujen kanssa, on tärkeää olla tietoinen mahdollisista suorituskykyvaikutuksista.
BigInt
-operaatiot voivat olla hitaampia kuin standarditNumber
-operaatiot.- Muuntaminen
BigInt
- jaNumber
-tyyppien välillä voi myös aiheuttaa lisäkuormaa.
Siksi käytä BigInt
-tyyppiä vain tarvittaessa ja optimoi koodisi suorituskyvyn kannalta, jos suoritat suuren määrän BigInt
-operaatioita.
Yhteenveto
BigInt
on arvokas lisä JavaScriptiin, joka mahdollistaa kehittäjien käsitellä suurten kokonaislukujen aritmetiikkaa tarkasti. Ymmärtämällä sen ominaisuudet, rajoitukset ja käyttötapaukset voit hyödyntää BigInt
-tyyppiä rakentaaksesi vakaita ja tarkkoja sovelluksia eri aloilla, kuten kryptografiassa, talouslaskelmissa ja tieteellisessä laskennassa. Muista ottaa huomioon selainyhteensopivuus ja suorituskykyvaikutukset, kun käytät BigInt
-tyyppiä projekteissasi.
Lisätietoa
- Mozilla Developer Network (MDN) - BigInt
- V8-blogi - BigInt: Mielivaltaisen tarkkuuden kokonaisluvut JavaScriptissä
Tämä opas tarjoaa kattavan yleiskatsauksen BigInt
-tyypistä JavaScriptissä. Tutustu linkitettyihin resursseihin saadaksesi syvällisempää tietoa ja edistyneempiä tekniikoita.