Suomi

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:

BigInt-arvojen luominen

JavaScriptissä on kaksi pääasiallista tapaa luoda BigInt-arvoja:

  1. Käyttämällä `BigInt()`-konstruktoria: Tämä konstruktori voi muuntaa numeron, merkkijonon tai boolean-arvon BigInt-tyypiksi.
  2. 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:

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:

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:

  1. Muunna merkkijonoksi: Muunna BigInt merkkijonoksi ennen serialisointia. Tämä on yleisin ja suoraviivaisin lähestymistapa.
  2. 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.

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

Tämä opas tarjoaa kattavan yleiskatsauksen BigInt-tyypistä JavaScriptissä. Tutustu linkitettyihin resursseihin saadaksesi syvällisempää tietoa ja edistyneempiä tekniikoita.