Vodič za JavaScript BigInt: prevladajte ograničenja brojeva i izvodite precizne izračune s velikim cijelim brojevima. Saznajte sve o njegovoj upotrebi i primjeni.
JavaScript BigInt: Ovladavanje aritmetikom velikih cijelih brojeva
Iako je svestran jezik, JavaScript ima ograničenja pri radu s vrlo velikim cijelim brojevima. Standardni `Number` tip može točno predstaviti cijele brojeve samo do određene granice, poznate kao `Number.MAX_SAFE_INTEGER`. Iznad te granice, izračuni postaju neprecizni, što dovodi do neočekivanih rezultata. Tu u pomoć priskače BigInt
. Predstavljen u ECMAScript 2020, BigInt
je ugrađeni objekt koji omogućuje predstavljanje i manipulaciju cijelim brojevima proizvoljne veličine, nadilazeći ograničenja standardnog `Number` tipa.
Razumijevanje potrebe za BigInt-om
Prije BigInt
-a, JavaScript programeri morali su se oslanjati na biblioteke ili prilagođene implementacije za rukovanje izračunima s velikim cijelim brojevima. Ta rješenja često su donosila dodatno opterećenje na performanse i povećanu složenost. Uvođenje BigInt
-a pružilo je nativan i učinkovit način rada s velikim cijelim brojevima, otvarajući mogućnosti za primjene u različitim domenama, uključujući:
- Kriptografija: Sigurno rukovanje velikim prostim brojevima ključno je za kriptografske algoritme.
- Financijski izračuni: Točno predstavljanje velikih novčanih vrijednosti bez gubitka preciznosti.
- Znanstveno računanje: Izvođenje složenih izračuna koji uključuju iznimno velike ili male brojeve.
- Vremenske oznake visoke preciznosti: Predstavljanje vremenskih oznaka s nanosekundnom preciznošću.
- Generiranje ID-ova: Stvaranje jedinstvenih i vrlo velikih identifikatora.
Stvaranje BigInt vrijednosti
Postoje dva osnovna načina za stvaranje BigInt
vrijednosti u JavaScriptu:
- Korištenjem `BigInt()` konstruktora: Ovaj konstruktor može pretvoriti broj, string ili logičku vrijednost u
BigInt
. - Korištenjem sufiksa `n`: Dodavanje `n` na cjelobrojni literal stvara
BigInt
.
Primjeri:
Korištenjem `BigInt()` konstruktora:
const bigIntFromNumber = BigInt(12345678901234567890);
const bigIntFromString = BigInt("98765432109876543210");
const bigIntFromBoolean = BigInt(true); // Rezultat je 1n
const bigIntFromFalseBoolean = BigInt(false); // Rezultat je 0n
console.log(bigIntFromNumber); // Izlaz: 12345678901234567890n
console.log(bigIntFromString); // Izlaz: 98765432109876543210n
console.log(bigIntFromBoolean); // Izlaz: 1n
console.log(bigIntFromFalseBoolean); // Izlaz: 0n
Korištenjem sufiksa `n`:
const bigIntLiteral = 12345678901234567890n;
console.log(bigIntLiteral); // Izlaz: 12345678901234567890n
Važna napomena: Ne možete izravno miješati BigInt
i Number
vrijednosti u aritmetičkim operacijama. Morate ih eksplicitno pretvoriti u isti tip prije izvođenja izračuna. Pokušaj njihovog izravnog miješanja rezultirat će TypeError
-om.
Aritmetičke operacije s BigInt-om
BigInt
podržava većinu standardnih aritmetičkih operatora, uključujući:
- Zbrajanje (`+`)
- Oduzimanje (`-`)
- Množenje (`*`)
- Dijeljenje (`/`)
- Ostatak pri dijeljenju (`%`)
- Potenciranje (`**`)
Primjeri:
const a = 12345678901234567890n;
const b = 98765432109876543210n;
const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // Napomena: Dijeljenje zaokružuje prema nuli
const remainder = a % 7n;
const power = a ** 3n; // Potenciranje radi kako se očekuje
console.log("Zbroj:", sum); // Izlaz: Zbroj: 111111111011111111100n
console.log("Razlika:", difference); // Izlaz: Razlika: -86419753208641975320n
console.log("Umnožak:", product); // Izlaz: Umnožak: 1219326311370217957951669538098765432100n
console.log("Kvocijent:", quotient); // Izlaz: Kvocijent: 6172839450617283945n
console.log("Ostatak:", remainder); // Izlaz: Ostatak: 5n
console.log("Potencija:", power); // Izlaz: Potencija: 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n
Važna razmatranja:
- Dijeljenje: Dijeljenje s
BigInt
vrijednostima zaokružuje prema nuli. To znači da se decimalni dio rezultata odbacuje. Ako trebate preciznije dijeljenje, razmislite o korištenju biblioteka koje podržavaju aritmetiku proizvoljne preciznosti. - Unarni plus operator (+): Unarni plus operator (+) ne može se koristiti s
BigInt
vrijednostima jer bi to bilo u sukobu sa starim asm.js kodom. Koristite funkciju za pretvorbu `Number()` kako biste `BigInt` pretvorili u `Number` ako vam je potrebna numerička reprezentacija (uz razumijevanje da biste mogli izgubiti preciznost). - Bitovni operatori:
BigInt
također podržava bitovne operatore kao što su `&`, `|`, `^`, `~`, `<<` i `>>`. Ovi operatori rade kako se i očekuje na binarnoj reprezentacijiBigInt
vrijednosti.
Operatori usporedbe
Možete koristiti standardne operatore usporedbe (`==`, `!=`, `<`, `>`, `<=`, `>=`) za usporedbu BigInt
vrijednosti s drugim BigInt
vrijednostima ili čak s Number
vrijednostima. Međutim, budite svjesni mogućnosti prisilne pretvorbe tipova (type coercion).
Primjeri:
const a = 10n;
const b = 20n;
const c = 10;
console.log(a == b); // Izlaz: false
console.log(a != b); // Izlaz: true
console.log(a < b); // Izlaz: true
console.log(a > b); // Izlaz: false
console.log(a <= b); // Izlaz: true
console.log(a >= b); // Izlaz: false
console.log(a == c); // Izlaz: true (prisilna pretvorba tipa)
console.log(a === c); // Izlaz: false (nema prisilne pretvorbe tipa)
Najbolja praksa: Koristite strogu jednakost (`===`) i strogu nejednakost (`!==`) kako biste izbjegli neočekivanu prisilnu pretvorbu tipova prilikom usporedbe BigInt
i Number
vrijednosti.
Pretvorba između BigInt-a i Number-a
Iako izravne aritmetičke operacije između BigInt
-a i Number
-a nisu dopuštene, možete pretvarati između ta dva tipa. Međutim, budite svjesni mogućeg gubitka preciznosti prilikom pretvaranja BigInt
-a u Number
ako BigInt
vrijednost premašuje `Number.MAX_SAFE_INTEGER`.
Primjeri:
const bigIntValue = 9007199254740991n; // Number.MAX_SAFE_INTEGER
const numberValue = Number(bigIntValue); // Pretvaranje BigInt-a u Number
console.log(numberValue); // Izlaz: 9007199254740991
const largerBigIntValue = 9007199254740992n; // Premašuje Number.MAX_SAFE_INTEGER
const largerNumberValue = Number(largerBigIntValue);
console.log(largerNumberValue); // Izlaz: 9007199254740992 (može biti neprecizno)
const numberToBigInt = BigInt(12345); // Pretvaranje Number-a u BigInt
console.log(numberToBigInt); // Izlaz: 12345n
Slučajevi upotrebe i primjeri
Kriptografija
Kriptografski algoritmi se često oslanjaju na vrlo velike proste brojeve radi sigurnosti. BigInt
pruža način za učinkovito predstavljanje i manipulaciju tim brojevima.
// Primjer: Generiranje jednostavnog (nesigurnog) para ključeva
function generateKeyPair() {
const p = 281n; // Prosti broj
const q = 283n; // Drugi prosti broj
const n = p * q; // Modul
const totient = (p - 1n) * (q - 1n); // Eulerova totient funkcija
// Odaberite e (javni eksponent) takav da je 1 < e < totient i gcd(e, totient) = 1
const e = 17n;
// Izračunajte d (privatni eksponent) takav da je (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("Javni ključ:", keyPair.publicKey);
console.log("Privatni ključ:", keyPair.privateKey);
Napomena: Ovo je pojednostavljeni primjer samo u svrhu demonstracije. Kriptografija u stvarnom svijetu koristi mnogo veće proste brojeve i sofisticiranije algoritme.
Financijski izračuni
Prilikom rada s velikim svotama novca, posebno u međunarodnim transakcijama, preciznost je ključna. BigInt
može spriječiti pogreške pri zaokruživanju i osigurati točne izračune.
// Primjer: Izračun složenih kamata
function calculateCompoundInterest(principal, rate, time) {
const principalBigInt = BigInt(principal * 100); // Pretvorite u cente
const rateBigInt = BigInt(rate * 10000); // Pretvorite u desettisućinke postotka
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% kamatna stopa
const time = 10; // 10 godina
const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("Konačni iznos:", finalAmount); // Izlaz: Konačni iznos: 1628894.6267774413 (približno)
U ovom primjeru, pretvaramo glavnicu i stopu u BigInt
vrijednosti kako bismo izbjegli pogreške pri zaokruživanju tijekom izračuna. Rezultat se zatim pretvara natrag u Number
za prikaz.
Rad s velikim ID-ovima
U distribuiranim sustavima, generiranje jedinstvenih ID-ova na više poslužitelja može biti izazovno. Korištenje BigInt
-a omogućuje vam stvaranje vrlo velikih ID-ova za koje je malo vjerojatno da će doći do kolizije.
// Primjer: Generiranje jedinstvenog ID-a na temelju vremenske oznake i ID-a poslužitelja
function generateUniqueId(serverId) {
const timestamp = BigInt(Date.now());
const serverIdBigInt = BigInt(serverId);
const random = BigInt(Math.floor(Math.random() * 1000)); // Dodajte malo nasumičnosti
// Kombinirajte vrijednosti kako biste stvorili jedinstveni ID
const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
return uniqueId.toString(); // Vratite kao string radi lakšeg rukovanja
}
const serverId = 123; // Primjer ID-a poslužitelja
const id1 = generateUniqueId(serverId);
const id2 = generateUniqueId(serverId);
console.log("Jedinstveni ID 1:", id1);
console.log("Jedinstveni ID 2:", id2);
BigInt i JSON
BigInt
vrijednosti nisu nativno podržane od strane JSON-a. Pokušaj serijalizacije JavaScript objekta koji sadrži BigInt
pomoću `JSON.stringify()` rezultirat će TypeError
-om. Za rukovanje BigInt
vrijednostima pri radu s JSON-om, imate nekoliko opcija:
- Pretvorba u string: Pretvorite
BigInt
u string prije serijalizacije. Ovo je najčešći i najjednostavniji pristup. - Prilagođena serijalizacija/deserijalizacija: Koristite prilagođenu funkciju za serijalizaciju/deserijalizaciju za rukovanje
BigInt
vrijednostima.
Primjeri:
Pretvaranje u string:
const data = {
id: 12345678901234567890n,
name: "Primjer podataka",
};
// Pretvorite BigInt u string prije serijalizacije
data.id = data.id.toString();
const jsonData = JSON.stringify(data);
console.log(jsonData); // Izlaz: {"id":"12345678901234567890","name":"Primjer podataka"}
// Prilikom deserijalizacije, morat ćete pretvoriti string natrag u BigInt
const parsedData = JSON.parse(jsonData, (key, value) => {
if (key === "id") {
return BigInt(value);
}
return value;
});
console.log(parsedData.id); // Izlaz: 12345678901234567890n
Prilagođena serijalizacija/deserijalizacija (pomoću `replacer`-a i `reviver`-a):
const data = {
id: 12345678901234567890n,
name: "Primjer podataka",
};
// Prilagođena serijalizacija
const jsonData = JSON.stringify(data, (key, value) => {
if (typeof value === 'bigint') {
return value.toString();
} else {
return value;
}
});
console.log(jsonData);
// Prilagođena deserijalizacija
const parsedData = JSON.parse(jsonData, (key, value) => {
if (typeof value === 'string' && /^[0-9]+$/.test(value)) { // provjerite je li to broj i string
try {
return BigInt(value);
} catch(e) {
return value;
}
}
return value;
});
console.log(parsedData.id);
Kompatibilnost s preglednicima
BigInt
je široko podržan u modernim preglednicima. Međutim, ključno je provjeriti kompatibilnost za starije preglednike ili okruženja. Možete koristiti alat kao što je Can I use za provjeru podrške u preglednicima. Ako trebate podržati starije preglednike, mogli biste razmisliti o korištenju polyfilla, ali budite svjesni da polyfillovi mogu utjecati na performanse.
Razmatranja o performansama
Iako BigInt
pruža moćan način za rad s velikim cijelim brojevima, važno je biti svjestan mogućih implikacija na performanse.
- Operacije s
BigInt
-om mogu biti sporije od standardnih operacija sNumber
-om. - Pretvaranje između
BigInt
-a iNumber
-a također može uvesti dodatno opterećenje.
Stoga, koristite BigInt
samo kada je to nužno i optimizirajte svoj kod za performanse ako izvodite veliki broj BigInt
operacija.
Zaključak
BigInt
je vrijedan dodatak JavaScriptu, omogućavajući programerima da s preciznošću rukuju aritmetikom velikih cijelih brojeva. Razumijevanjem njegovih značajki, ograničenja i slučajeva upotrebe, možete iskoristiti BigInt
za izgradnju robusnih i točnih aplikacija u različitim domenama, uključujući kriptografiju, financijske izračune i znanstveno računanje. Ne zaboravite uzeti u obzir kompatibilnost s preglednicima i implikacije na performanse kada koristite BigInt
u svojim projektima.
Daljnje istraživanje
- Mozilla Developer Network (MDN) - BigInt
- V8 Blog - BigInt: Cijeli brojevi proizvoljne preciznosti u JavaScriptu
Ovaj vodič pruža sveobuhvatan pregled BigInt
-a u JavaScriptu. Istražite povezane resurse za detaljnije informacije i napredne tehnike.