فارسی

راهنمای جامع نوع BigInt در جاوا اسکریپت، شامل ویژگی‌ها، کاربردها و نحوه استفاده در محاسبات اعداد صحیح بزرگ. بیاموزید چگونه بر محدودیت‌های جاوا اسکریپت غلبه کرده و محاسبات پیچیده را با دقت انجام دهید.

جاوا اسکریپت BigInt: تسلط بر محاسبات اعداد صحیح بزرگ

جاوا اسکریپت، با وجود اینکه یک زبان همه‌کاره است، در کار با اعداد صحیح بسیار بزرگ محدودیت‌هایی دارد. نوع استاندارد `Number` تنها می‌تواند اعداد صحیح را تا یک حد معین، که به نام `Number.MAX_SAFE_INTEGER` شناخته می‌شود، به طور دقیق نمایش دهد. فراتر از این حد، محاسبات غیردقیق شده و به نتایج غیرمنتظره منجر می‌شود. اینجاست که BigInt به کمک می‌آید. BigInt که در ECMAScript 2020 معرفی شد، یک شیء داخلی است که راهی برای نمایش و دستکاری اعداد صحیح با اندازه دلخواه فراهم می‌کند و از محدودیت‌های نوع استاندارد `Number` فراتر می‌رود.

درک نیاز به BigInt

قبل از BigInt، توسعه‌دهندگان جاوا اسکریپت مجبور بودند برای انجام محاسبات با اعداد صحیح بزرگ به کتابخانه‌ها یا پیاده‌سازی‌های سفارشی تکیه کنند. این راه‌حل‌ها اغلب با سربار عملکردی و افزایش پیچیدگی همراه بودند. معرفی BigInt یک روش بومی و کارآمد برای کار با اعداد صحیح بزرگ فراهم کرد و امکاناتی را برای کاربردها در حوزه‌های مختلف باز نمود، از جمله:

ایجاد مقادیر BigInt

دو راه اصلی برای ایجاد مقادیر BigInt در جاوا اسکریپت وجود دارد:

  1. استفاده از سازنده `BigInt()`: این سازنده می‌تواند یک عدد، رشته یا مقدار بولی را به یک BigInt تبدیل کند.
  2. استفاده از پسوند `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 یا حتی با مقادیر 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، چند گزینه دارید:

  1. تبدیل به رشته: قبل از سریالایز کردن، BigInt را به رشته تبدیل کنید. این رایج‌ترین و سرراست‌ترین رویکرد است.
  2. سریالایز/دی‌سریالایز سفارشی: از یک تابع سریالایز/دی‌سریالایز سفارشی برای مدیریت مقادیر 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 استفاده کنید و اگر تعداد زیادی عملیات BigInt انجام می‌دهید، کد خود را برای عملکرد بهینه کنید.

نتیجه‌گیری

BigInt یک افزودنی ارزشمند به جاوا اسکریپت است که به توسعه‌دهندگان امکان می‌دهد محاسبات با اعداد صحیح بزرگ را با دقت انجام دهند. با درک ویژگی‌ها، محدودیت‌ها و موارد استفاده آن، می‌توانید از BigInt برای ساخت برنامه‌های کاربردی قوی و دقیق در حوزه‌های مختلف، از جمله رمزنگاری، محاسبات مالی و محاسبات علمی، بهره‌برداری کنید. به یاد داشته باشید که هنگام استفاده از BigInt در پروژه‌های خود، سازگاری با مرورگرها و پیامدهای عملکردی را در نظر بگیرید.

برای مطالعه بیشتر

این راهنما یک نمای کلی جامع از BigInt در جاوا اسکریپت ارائه می‌دهد. برای اطلاعات عمیق‌تر و تکنیک‌های پیشرفته، منابع لینک‌شده را بررسی کنید.