راهنمای جامع نوع BigInt در جاوا اسکریپت، شامل ویژگیها، کاربردها و نحوه استفاده در محاسبات اعداد صحیح بزرگ. بیاموزید چگونه بر محدودیتهای جاوا اسکریپت غلبه کرده و محاسبات پیچیده را با دقت انجام دهید.
جاوا اسکریپت BigInt: تسلط بر محاسبات اعداد صحیح بزرگ
جاوا اسکریپت، با وجود اینکه یک زبان همهکاره است، در کار با اعداد صحیح بسیار بزرگ محدودیتهایی دارد. نوع استاندارد `Number` تنها میتواند اعداد صحیح را تا یک حد معین، که به نام `Number.MAX_SAFE_INTEGER` شناخته میشود، به طور دقیق نمایش دهد. فراتر از این حد، محاسبات غیردقیق شده و به نتایج غیرمنتظره منجر میشود. اینجاست که BigInt
به کمک میآید. BigInt
که در ECMAScript 2020 معرفی شد، یک شیء داخلی است که راهی برای نمایش و دستکاری اعداد صحیح با اندازه دلخواه فراهم میکند و از محدودیتهای نوع استاندارد `Number` فراتر میرود.
درک نیاز به BigInt
قبل از BigInt
، توسعهدهندگان جاوا اسکریپت مجبور بودند برای انجام محاسبات با اعداد صحیح بزرگ به کتابخانهها یا پیادهسازیهای سفارشی تکیه کنند. این راهحلها اغلب با سربار عملکردی و افزایش پیچیدگی همراه بودند. معرفی BigInt
یک روش بومی و کارآمد برای کار با اعداد صحیح بزرگ فراهم کرد و امکاناتی را برای کاربردها در حوزههای مختلف باز نمود، از جمله:
- رمزنگاری: مدیریت امن اعداد اول بزرگ برای الگوریتمهای رمزنگاری حیاتی است.
- محاسبات مالی: نمایش دقیق مقادیر پولی بزرگ بدون از دست دادن دقت.
- محاسبات علمی: انجام محاسبات پیچیده شامل اعداد بسیار بزرگ یا کوچک.
- برچسبهای زمانی با دقت بالا: نمایش برچسبهای زمانی با دقت نانوثانیه.
- تولید شناسه (ID): ایجاد شناسههای منحصربهفرد و بسیار بزرگ.
ایجاد مقادیر BigInt
دو راه اصلی برای ایجاد مقادیر BigInt
در جاوا اسکریپت وجود دارد:
- استفاده از سازنده `BigInt()`: این سازنده میتواند یک عدد، رشته یا مقدار بولی را به یک
BigInt
تبدیل کند. - استفاده از پسوند `n`: اضافه کردن `n` به یک عدد صحیح لیترال، یک
BigInt
ایجاد میکند.
مثالها:
استفاده از سازنده `BigInt()`:
const bigIntFromNumber = BigInt(12345678901234567890);
const bigIntFromString = BigInt("98765432109876543210");
const bigIntFromBoolean = BigInt(true); // نتیجه 1n میشود
const bigIntFromFalseBoolean = BigInt(false); // نتیجه 0n میشود
console.log(bigIntFromNumber); // خروجی: 12345678901234567890n
console.log(bigIntFromString); // خروجی: 98765432109876543210n
console.log(bigIntFromBoolean); // خروجی: 1n
console.log(bigIntFromFalseBoolean); // خروجی: 0n
استفاده از پسوند `n`:
const bigIntLiteral = 12345678901234567890n;
console.log(bigIntLiteral); // خروجی: 12345678901234567890n
نکته مهم: شما نمیتوانید مقادیر BigInt
و Number
را مستقیماً در عملیات حسابی با هم ترکیب کنید. باید قبل از انجام محاسبات، آنها را به صراحت به یک نوع تبدیل کنید. تلاش برای ترکیب مستقیم آنها منجر به یک `TypeError` خواهد شد.
عملیات حسابی با BigInt
BigInt
از اکثر عملگرهای حسابی استاندارد پشتیبانی میکند، از جمله:
- جمع (`+`)
- تفریق (`-`)
- ضرب (`*`)
- تقسیم (`/`)
- باقیمانده (`%`)
- توان (`**`)
مثالها:
const a = 12345678901234567890n;
const b = 98765432109876543210n;
const sum = a + b;
const difference = a - b;
const product = a * b;
const quotient = a / 2n; // توجه: تقسیم به سمت صفر گرد میشود
const remainder = a % 7n;
const power = a ** 3n; // توانرسانی همانطور که انتظار میرود کار میکند
console.log("جمع:", sum); // خروجی: جمع: 111111111011111111100n
console.log("تفاضل:", difference); // خروجی: تفاضل: -86419753208641975320n
console.log("حاصلضرب:", product); // خروجی: حاصلضرب: 1219326311370217957951669538098765432100n
console.log("خارج قسمت:", quotient); // خروجی: خارج قسمت: 6172839450617283945n
console.log("باقیمانده:", remainder); // خروجی: باقیمانده: 5n
console.log("توان:", power); // خروجی: توان: 188167637178915486089706900615238656561139712n
ملاحظات مهم:
- تقسیم: تقسیم با مقادیر
BigInt
به سمت صفر گرد میشود. این بدان معناست که قسمت اعشاری نتیجه حذف میشود. اگر به تقسیم دقیقتری نیاز دارید، از کتابخانههایی که از محاسبات با دقت دلخواه پشتیبانی میکنند، استفاده کنید. - عملگر مثبت یگانی (+): عملگر مثبت یگانی (+) را نمیتوان با مقادیر
BigInt
استفاده کرد زیرا با کدهای قدیمی asm.js تداخل ایجاد میکند. اگر به نمایش عددی نیاز دارید (با درک این که ممکن است دقت را از دست بدهید)، از تابع تبدیل `Number()` برای تبدیل یک BigInt به یک Number استفاده کنید. - عملگرهای بیتی:
BigInt
همچنین از عملگرهای بیتی مانند `&`, `|`, `^`, `~`, `<<`, و `>>` پشتیبانی میکند. این عملگرها همانطور که انتظار میرود بر روی نمایش باینری مقادیرBigInt
کار میکنند.
عملگرهای مقایسهای
شما میتوانید از عملگرهای مقایسهای استاندارد (`==`, `!=`, `<`, `>`, `<=`, `>=`) برای مقایسه مقادیر BigInt
با دیگر مقادیر BigInt
یا حتی با مقادیر Number
استفاده کنید. با این حال، به پتانسیل تبدیل نوع ضمنی توجه داشته باشید.
مثالها:
const a = 10n;
const b = 20n;
const c = 10;
console.log(a == b); // خروجی: false
console.log(a != b); // خروجی: true
console.log(a < b); // خروجی: true
console.log(a > b); // خروجی: false
console.log(a <= b); // خروجی: true
console.log(a >= b); // خروجی: false
console.log(a == c); // خروجی: true (تبدیل نوع ضمنی)
console.log(a === c); // خروجی: false (بدون تبدیل نوع ضمنی)
بهترین روش: برای جلوگیری از تبدیل نوع غیرمنتظره هنگام مقایسه مقادیر BigInt
و Number
، از برابری اکید (`===`) و نابرابری اکید (`!==`) استفاده کنید.
تبدیل بین BigInt و Number
در حالی که عملیات حسابی مستقیم بین BigInt
و Number
مجاز نیست، شما میتوانید بین این دو نوع تبدیل انجام دهید. با این حال، هنگام تبدیل یک BigInt
به یک Number
اگر مقدار BigInt
از `Number.MAX_SAFE_INTEGER` بیشتر باشد، از پتانسیل از دست رفتن دقت آگاه باشید.
مثالها:
const bigIntValue = 9007199254740991n; // Number.MAX_SAFE_INTEGER
const numberValue = Number(bigIntValue); // تبدیل BigInt به Number
console.log(numberValue); // خروجی: 9007199254740991
const largerBigIntValue = 9007199254740992n; // فراتر از Number.MAX_SAFE_INTEGER
const largerNumberValue = Number(largerBigIntValue);
console.log(largerNumberValue); // خروجی: 9007199254740992 (ممکن است غیردقیق باشد)
const numberToBigInt = BigInt(12345); // تبدیل Number به BigInt
console.log(numberToBigInt); // خروجی: 12345n
موارد استفاده و مثالها
رمزنگاری
الگوریتمهای رمزنگاری اغلب برای امنیت به اعداد اول بسیار بزرگ تکیه میکنند. BigInt
راهی برای نمایش و دستکاری کارآمد این اعداد فراهم میکند.
// مثال: تولید یک زوج کلید ساده (ناامن)
function generateKeyPair() {
const p = 281n; // یک عدد اول
const q = 283n; // یک عدد اول دیگر
const n = p * q; // مدول
const totient = (p - 1n) * (q - 1n); // تابع فی اویلر
// انتخاب یک e (توان عمومی) به طوری که 1 < e < totient و gcd(e, totient) = 1
const e = 17n;
// محاسبه d (توان خصوصی) به طوری که (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("کلید عمومی:", keyPair.publicKey);
console.log("کلید خصوصی:", keyPair.privateKey);
توجه: این یک مثال سادهشده فقط برای اهداف نمایشی است. رمزنگاری در دنیای واقعی از اعداد اول بسیار بزرگتر و الگوریتمهای پیچیدهتری استفاده میکند.
محاسبات مالی
هنگام کار با مبالغ بزرگ پول، به ویژه در معاملات بینالمللی، دقت بسیار مهم است. BigInt
میتواند از خطاهای گرد کردن جلوگیری کرده و محاسبات دقیق را تضمین کند.
// مثال: محاسبه سود مرکب
function calculateCompoundInterest(principal, rate, time) {
const principalBigInt = BigInt(principal * 100); // تبدیل به سنت
const rateBigInt = BigInt(rate * 10000); // تبدیل به یک دههزارم درصد
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%
const time = 10; // 10 سال
const finalAmount = calculateCompoundInterest(principal, rate, time);
console.log("مبلغ نهایی:", finalAmount); // خروجی: مبلغ نهایی: 1628894.6267774413 (تقریباً)
در این مثال، ما اصل پول و نرخ را به مقادیر BigInt
تبدیل میکنیم تا از خطاهای گرد کردن در طول محاسبه جلوگیری کنیم. سپس نتیجه برای نمایش به یک Number
تبدیل میشود.
کار با شناسههای (ID) بزرگ
در سیستمهای توزیعشده، تولید شناسههای منحصربهفرد در چندین سرور میتواند چالشبرانگیز باشد. استفاده از BigInt
به شما امکان میدهد شناسههای بسیار بزرگی ایجاد کنید که احتمال برخورد آنها کم است.
// مثال: تولید یک شناسه منحصربهفرد بر اساس برچسب زمانی و شناسه سرور
function generateUniqueId(serverId) {
const timestamp = BigInt(Date.now());
const serverIdBigInt = BigInt(serverId);
const random = BigInt(Math.floor(Math.random() * 1000)); // اضافه کردن کمی تصادفی بودن
// ترکیب مقادیر برای ایجاد یک شناسه منحصربهفرد
const uniqueId = (timestamp << 20n) + (serverIdBigInt << 10n) + random;
return uniqueId.toString(); // بازگرداندن به عنوان رشته برای مدیریت آسان
}
const serverId = 123; // شناسه سرور مثال
const id1 = generateUniqueId(serverId);
const id2 = generateUniqueId(serverId);
console.log("شناسه منحصربهفرد ۱:", id1);
console.log("شناسه منحصربهفرد ۲:", id2);
BigInt و JSON
مقادیر BigInt
به طور بومی توسط JSON پشتیبانی نمیشوند. تلاش برای سریالایز کردن یک شیء جاوا اسکریپت حاوی یک BigInt
با استفاده از `JSON.stringify()` منجر به یک `TypeError` خواهد شد. برای مدیریت مقادیر BigInt
هنگام کار با JSON، چند گزینه دارید:
- تبدیل به رشته: قبل از سریالایز کردن،
BigInt
را به رشته تبدیل کنید. این رایجترین و سرراستترین رویکرد است. - سریالایز/دیسریالایز سفارشی: از یک تابع سریالایز/دیسریالایز سفارشی برای مدیریت مقادیر
BigInt
استفاده کنید.
مثالها:
تبدیل به رشته:
const data = {
id: 12345678901234567890n,
name: "داده مثال",
};
// تبدیل BigInt به رشته قبل از سریالایز کردن
data.id = data.id.toString();
const jsonData = JSON.stringify(data);
console.log(jsonData); // خروجی: {"id":"12345678901234567890","name":"داده مثال"}
// هنگام دیسریالایز کردن، باید رشته را دوباره به BigInt تبدیل کنید
const parsedData = JSON.parse(jsonData, (key, value) => {
if (key === "id") {
return BigInt(value);
}
return value;
});
console.log(parsedData.id); // خروجی: 12345678901234567890n
سریالایز/دیسریالایز سفارشی (با استفاده از `replacer` و `reviver`):
const data = {
id: 12345678901234567890n,
name: "داده مثال",
};
// سریالایز سفارشی
const jsonData = JSON.stringify(data, (key, value) => {
if (typeof value === 'bigint') {
return value.toString();
} else {
return value;
}
});
console.log(jsonData);
// دیسریالایز سفارشی
const parsedData = JSON.parse(jsonData, (key, value) => {
if (typeof value === 'string' && /^[0-9]+$/.test(value)) { // بررسی میکند که آیا یک عدد و رشته است
try {
return BigInt(value);
} catch(e) {
return value;
}
}
return value;
});
console.log(parsedData.id);
سازگاری با مرورگرها
BigInt
به طور گسترده در مرورگرهای مدرن پشتیبانی میشود. با این حال، بررسی سازگاری برای مرورگرها یا محیطهای قدیمیتر ضروری است. میتوانید از ابزاری مانند Can I use برای تأیید پشتیبانی مرورگرها استفاده کنید. اگر نیاز به پشتیبانی از مرورگرهای قدیمی دارید، ممکن است استفاده از یک polyfill را در نظر بگیرید، اما آگاه باشید که polyfillها میتوانند بر عملکرد تأثیر بگذارند.
ملاحظات عملکردی
در حالی که BigInt
روشی قدرتمند برای کار با اعداد صحیح بزرگ فراهم میکند، مهم است که از پیامدهای عملکردی بالقوه آن آگاه باشید.
- عملیات
BigInt
میتواند کندتر از عملیات استانداردNumber
باشد. - تبدیل بین
BigInt
وNumber
نیز میتواند سربار ایجاد کند.
بنابراین، فقط در مواقع ضروری از BigInt
استفاده کنید و اگر تعداد زیادی عملیات BigInt
انجام میدهید، کد خود را برای عملکرد بهینه کنید.
نتیجهگیری
BigInt
یک افزودنی ارزشمند به جاوا اسکریپت است که به توسعهدهندگان امکان میدهد محاسبات با اعداد صحیح بزرگ را با دقت انجام دهند. با درک ویژگیها، محدودیتها و موارد استفاده آن، میتوانید از BigInt
برای ساخت برنامههای کاربردی قوی و دقیق در حوزههای مختلف، از جمله رمزنگاری، محاسبات مالی و محاسبات علمی، بهرهبرداری کنید. به یاد داشته باشید که هنگام استفاده از BigInt
در پروژههای خود، سازگاری با مرورگرها و پیامدهای عملکردی را در نظر بگیرید.
برای مطالعه بیشتر
- شبکه توسعهدهندگان موزیلا (MDN) - BigInt
- وبلاگ V8 - BigInt: اعداد صحیح با دقت دلخواه در جاوا اسکریپت
این راهنما یک نمای کلی جامع از BigInt
در جاوا اسکریپت ارائه میدهد. برای اطلاعات عمیقتر و تکنیکهای پیشرفته، منابع لینکشده را بررسی کنید.