العربية

دليل شامل لنوع BigInt في جافاسكريبت، يغطي ميزاته واستخداماته وتطبيقاته في التعامل مع حسابات الأعداد الصحيحة الكبيرة. تعلم كيفية التغلب على قيود جافاسكريبت وإجراء العمليات الحسابية المعقدة بدقة.

JavaScript 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); // الناتج: الأس: 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n

اعتبارات هامة:

عوامل المقارنة

يمكنك استخدام عوامل المقارنة القياسية (`==`، `!=`، `<`، `>`، `<=`، `>=`) لمقارنة قيم BigInt مع قيم BigInt أخرى أو حتى مع قيم Number. ومع ذلك، كن على دراية بإمكانية الإكراه النوعي (type coercion).

أمثلة:


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); // دالة أويلر totient

  // اختر 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 للعرض.

العمل مع المعرفات الكبيرة (IDs)

في الأنظمة الموزعة، يمكن أن يكون إنشاء معرفات فريدة عبر خوادم متعددة تحديًا. يتيح لك استخدام 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("المعرف الفريد 1:", id1);
console.log("المعرف الفريد 2:", id2);

BigInt و JSON

قيم BigInt غير مدعومة أصلاً بواسطة JSON. ستؤدي محاولة تحويل كائن جافاسكريبت يحتوي على BigInt باستخدام `JSON.stringify()` إلى خطأ `TypeError`. للتعامل مع قيم BigInt عند العمل مع JSON، لديك خياران:

  1. التحويل إلى سلسلة نصية: قم بتحويل BigInt إلى سلسلة نصية قبل التحويل إلى JSON. هذا هو النهج الأكثر شيوعًا ومباشرة.
  2. التحويل المخصص (Serialization/Deserialization): استخدم دالة تحويل/فك تحويل مخصصة للتعامل مع قيم BigInt.

أمثلة:

التحويل إلى سلسلة نصية:


const data = {
  id: 12345678901234567890n,
  name: "Example Data",
};

// تحويل BigInt إلى سلسلة نصية قبل التحويل إلى JSON
data.id = data.id.toString();

const jsonData = JSON.stringify(data);
console.log(jsonData); // الناتج: {"id":"12345678901234567890","name":"Example Data"}

// عند فك التحويل، ستحتاج إلى تحويل السلسلة النصية مرة أخرى إلى 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: "Example Data",
};

// تحويل مخصص
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، ولكن كن على دراية بأن polyfills يمكن أن تؤثر على الأداء.

اعتبارات الأداء

بينما يوفر BigInt طريقة قوية للعمل مع الأعداد الصحيحة الكبيرة، من المهم أن تكون على دراية بالآثار المحتملة على الأداء.

لذلك، استخدم BigInt فقط عند الضرورة، وقم بتحسين الكود الخاص بك من أجل الأداء إذا كنت تقوم بعدد كبير من عمليات BigInt.

الخاتمة

يعد BigInt إضافة قيمة إلى جافاسكريبت، مما يمكّن المطورين من التعامل مع حسابات الأعداد الصحيحة الكبيرة بدقة. من خلال فهم ميزاته وقيوده وحالات استخدامه، يمكنك الاستفادة من BigInt لبناء تطبيقات قوية ودقيقة في مجالات مختلفة، بما في ذلك التشفير والحسابات المالية والحوسبة العلمية. تذكر أن تأخذ في الاعتبار توافق المتصفحات والآثار المترتبة على الأداء عند استخدام BigInt في مشاريعك.

لمزيد من الاطلاع

يقدم هذا الدليل نظرة شاملة على BigInt في جافاسكريبت. استكشف الموارد المرتبطة لمزيد من المعلومات المتعمقة والتقنيات المتقدمة.