Lietuvių

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:

BigInt reikšmių kūrimas

Yra du pagrindiniai būdai sukurti BigInt reikšmes JavaScript:

  1. Naudojant `BigInt()` konstruktorių: Šis konstruktorius gali konvertuoti skaičių, eilutę ar loginę reikšmę į BigInt.
  2. 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:

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:

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ų:

  1. Konvertuoti į eilutę: Prieš serializuojant, konvertuokite BigInt į eilutę. Tai yra labiausiai paplitęs ir tiesiausias būdas.
  2. 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.

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

Šis vadovas pateikia išsamią BigInt apžvalgą JavaScript kalboje. Išsamesnės informacijos ir pažangesnių technikų ieškokite nurodytuose šaltiniuose.