دليل شامل لنوع BigInt في جافاسكريبت، يغطي ميزاته واستخداماته وتطبيقاته في التعامل مع حسابات الأعداد الصحيحة الكبيرة. تعلم كيفية التغلب على قيود جافاسكريبت وإجراء العمليات الحسابية المعقدة بدقة.
JavaScript 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); // الناتج: الأس: 187641281029182300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n
اعتبارات هامة:
- القسمة: القسمة باستخدام قيم
BigInt
تقرب نحو الصفر. هذا يعني أنه يتم تجاهل الجزء العشري من النتيجة. إذا كنت بحاجة إلى قسمة أكثر دقة، ففكر في استخدام مكتبات تدعم الحسابات ذات الدقة التعسفية. - عامل الزائد الأحادي (+): لا يمكن استخدام عامل الزائد الأحادي (+) مع قيم
BigInt
لأنه يتعارض مع كود asm.js القديم. استخدم دالة التحويل `Number()` لتحويل BigInt إلى Number إذا كنت تحتاج إلى تمثيل رقمي (مع فهم أنك قد تفقد الدقة). - عوامل التشغيل على مستوى البت (Bitwise Operators): يدعم
BigInt
أيضًا عوامل التشغيل على مستوى البت مثل `&`، `|`، `^`، `~`، `<<`، و `>>`. تعمل هذه العوامل كما هو متوقع على التمثيل الثنائي لقيمBigInt
.
عوامل المقارنة
يمكنك استخدام عوامل المقارنة القياسية (`==`، `!=`، `<`، `>`، `<=`، `>=`) لمقارنة قيم 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، لديك خياران:
- التحويل إلى سلسلة نصية: قم بتحويل
BigInt
إلى سلسلة نصية قبل التحويل إلى JSON. هذا هو النهج الأكثر شيوعًا ومباشرة. - التحويل المخصص (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
أبطأ من عملياتNumber
القياسية. - يمكن أن يؤدي التحويل بين
BigInt
وNumber
أيضًا إلى عبء إضافي.
لذلك، استخدم BigInt
فقط عند الضرورة، وقم بتحسين الكود الخاص بك من أجل الأداء إذا كنت تقوم بعدد كبير من عمليات BigInt
.
الخاتمة
يعد BigInt
إضافة قيمة إلى جافاسكريبت، مما يمكّن المطورين من التعامل مع حسابات الأعداد الصحيحة الكبيرة بدقة. من خلال فهم ميزاته وقيوده وحالات استخدامه، يمكنك الاستفادة من BigInt
لبناء تطبيقات قوية ودقيقة في مجالات مختلفة، بما في ذلك التشفير والحسابات المالية والحوسبة العلمية. تذكر أن تأخذ في الاعتبار توافق المتصفحات والآثار المترتبة على الأداء عند استخدام BigInt
في مشاريعك.
لمزيد من الاطلاع
يقدم هذا الدليل نظرة شاملة على BigInt
في جافاسكريبت. استكشف الموارد المرتبطة لمزيد من المعلومات المتعمقة والتقنيات المتقدمة.