عوامل الحساب الثنائي ECMAScript

عوامل الحساب تقوم بعملية على المستوى الأساسي للرقم (أي 32 رقماً يمثلون الرقم)

استعراض الأعداد

يوجد نوعان من الأعداد في ECMAScript، الأعداد الصحيحة (المسموح باستخدام الأعداد الإيجابية والسلبية) والأعداد غير الصحيحة (المسموح باستخدام الأعداد الإيجابية فقط). في ECMAScript، جميع الأعداد المكتوبة بالكتابة تكون أعداد صحيحة، ماذا يعني ذلك؟

يستخدم الأعداد الصحيحة 31 رقماً لتمثيل قيمة الأعداد، ويستخدم الرقم 32 لتمثيل إشارة الأعداد، 0 تمثل الأعداد الإيجابية، و1 تمثل الأعداد السلبية. نطاق القيم من -2147483648 إلى 2147483647.

يمكن حفظ الأعداد الصحيحة الثنائية بنوعين مختلفين، واحد用于 حفظ الأعداد الإيجابية، والآخر用于 حفظ الأعداد السلبية. يتم حفظ الأعداد الإيجابية بأسلوب ثنائي حقيقي، حيث يمثل كل رقم من الأرقام ال 31 الرقم في قوة 2، من الرقم الأول (الرقم 0)، الذي يمثل 20،الرقم الثاني (الرقم 1) يمثل 21الأرقام غير المستخدمة يتم ملؤها بـ 0، أي يتم تجاهلها. على سبيل المثال، يظهر الشكل التالي تمثيل عدد 18.

عدد ثنائي عشري ذو إشارة 32 بت

استخدمت نسخة ثنائية عدد 18 فقط 5 أرقام في البداية، وهي أرقام فعالة هذا الرقم. إذا قمت بتحويل الرقم إلى سلسلة ثنائية، يمكنك رؤية الأرقام الفعالة:

var iNum = 18;
alert(iNum.toString(2));	//يخرج "10010"

هذا الكود يخرج فقط "10010" وليس تمثيل 32 بت لعدد 18. الأرقام الأخرى ليست مهمة لأنه يمكن تحديد القيمة العشرية باستخدام 5 أرقام فقط. كما هو موضح في الشكل التالي:

عدد ثنائي ذو 5 أرقام هو 18

تخزن الأعداد السلبية أيضًا كرمز ثنائي، ولكن باستخدام نظام الإشارة الثنائي. تتكون خطوات حساب إشارة الأعداد الثنائية الثلاثة:

  1. تحديد تمثيل الأعداد الإيجابية غير المعدومة الثنائي (على سبيل المثال، لتحديد تمثيل إشارة -18 الثنائي، يجب أولاً تحديد تمثيل 18 الثنائي)
  2. حساب النظام الثنائي للنقيض، وهو ما يعني استبدال 0 بـ 1 واستبدال 1 بـ 0
  3. إضافة 1 إلى النظام الثنائي للنقيض

لتحديد تمثيل -18 الثنائي، يجب أولاً الحصول على تمثيل 18 الثنائي، كما يلي:

0000 0000 0000 0000 0000 0000 0001 0010

في البداية، يتم حساب النظام الثنائي للنقيض، كما يلي:

1111 1111 1111 1111 1111 1111 1110 1101

في النهاية، يتم إضافة 1 إلى النظام الثنائي للنقيض، كما يلي:

1111 1111 1111 1111 1111 1111 1110 1101
                                      1
---------------------------------------
1111 1111 1111 1111 1111 1111 1110 1110

لذلك، فإن تمثيل -18 الثنائي هو 1111 1111 1111 1111 1111 1111 1110 1110. تذكر، عند معالجة الأعداد الصحيحة العلامتها إيجابية، لا يمكن للمطورين الوصول إلى البت 31.

من المثير للاهتمام أن ECMAScript لا يعرض الأعداد السلبية بشكل نظام ثنائي للإشارة، بل يعرضها بشكل نظام ثنائي للقيمة الإيجابية المسبوقة بناقص. على سبيل المثال:

var iNum = -18;
alert(iNum.toString(2));	//يُخرج "-10010"

هذا الكود يخرج "-10010" بدلاً من النظام الثنائي للإشارة، وهو لمنع الوصول إلى البت 31. لسهولة الاستخدام، يستخدم ECMAScript طريقة بسيطة لمعالجة الأعداد، حيث لا يجب على المطورين أن يهتموا باستخدامها.

من ناحية أخرى، تقوم الأعداد الصحيحة العلامتها سالبة بمعالجة البت الأخير كبت إضافي. في هذا النمط، لا يُعتبر البت 32 رمزًا للعلامة الإيجابية أو السلبية للعدد، بل له قيمة 2.31. بسبب هذا البت الإضافي، يتراوح نطاق الأعداد الصحيحة العلامتها سالبة بين 0 و 4294967295. تبدو الأعداد الصحيحة العلامتها سالبة أقل من 2147483647 مثل الأعداد الصحيحة العلامتها إيجابية، بينما يجب استخدام البت 31 (في الأعداد الصحيحة العلامتها إيجابية، يكون هذا البت دائمًا 0) للأعداد الصحيحة العلامتها سالبة أكبر من 2147483647.

بعد تحويل الأعداد الصحيحة العلامتها سالبة إلى سلسلة من الأحرف، يتم إرجاع فقط الأعداد الموجودة في الأعداد.

ملاحظة:جميع الأرقام الصحيحة المكتوبة بشكل مباشر يتم حفظها بشكل افتراضي كعدد صحيح علامته إيجابية. يمكن لعمليات الحساب الموضعي في ECMAScript فقط إنشاء أعداد صحيحة علامتها سالبة.

عمليات الحساب الموضعي NOT

عمليات الحساب الموضعي NOT يتم تمثيلها بـ (~)، وهي واحدة من القليلة التي تتعلق بحسابات الأعداد الثنائية في ECMAScript.

عمودية NOT هي عملية ثلاثية:

  1. تحويل العدد إلى 32 موضع
  2. تحويل عدد ثنائي إلى شيفرة عكسية
  3. تحويل عدد ثنائي إلى عدد عشري

على سبيل المثال:

var iNum1 = 25;		//25 يساوي 00000000000000000000000000011001
var iNum2 = ~iNum1;	//تحويل إلى 11111111111111111111111111100110
alert(iNum2);		//يظهر "-26"

عمودية NOT هي في الواقع إيجابية العدد، ثم النقص 1، لذا 25 يصبح -26. يمكن الحصول على نفس النتيجة بالطريقة التالية:

var iNum1 = 25;
var iNum2 = -iNum1 -1;
alert(iNum2);	//يظهر "-26"

عمودية AND

عمودية AND تعرف بتسمية (&) وهي تعمل مباشرة على شكل البايت الثنائي للعدد. تقارن كل موضع من العددين، ثم تطبق القواعد التالية على المواضع المتطابقة:

الرقم في الرقم الأول الرقم في الرقم الثاني النتيجة
1 1 1
1 0 0
0 1 0
0 0 0

على سبيل المثال، إذا كنت تريد جمع 25 و 3، الكود كالتالي:

var iResult = 25 & 3;
alert(iResult);	//يظهر "1"

نتيجة جمع 25 و 3 هي 1. لماذا؟ تحليل كالتالي:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001
  3 = 0000 0000 0000 0000 0000 0000 0000 0011
---------------------------------------------
AND = 0000 0000 0000 0000 0000 0000 0000 0001

يمكن رؤية ذلك، في 25 و 3، هناك موضع واحد فقط (الموضع 0) يحتوي على 1 في نفسه، لذا، فإن جميع المواضع الأخرى تولد 0، لذا النتيجة هي 1.

عمودية OR

عمودية OR تعرف بتسمية (|) وهي تعمل مباشرة على شكل البايت الثنائي للعدد. عند حساب كل موضع، يستخدم عمودية OR القواعد التالية:

الرقم في الرقم الأول الرقم في الرقم الثاني النتيجة
1 1 1
1 0 1
0 1 1
0 0 0

بالنسبة للنموذج الذي يستخدم عمودية OR، يتم جمع 25 و 3، وكما يلي الكود:

var iResult = 25 | 3;
alert(iResult);	//يظهر "27"

نتيجة جمع 25 و 3 هي 27:

25 = 0000 0000 0000 0000 0000 0000 0001 1001
 3 = 0000 0000 0000 0000 0000 0000 0000 0011
--------------------------------------------
OR = 0000 0000 0000 0000 0000 0000 0001 1011

يمكن رؤية ذلك، في العددين، هناك 4 أرقام في نفس الموقع تحتوي على 1، وتتم نقل هذه الأرقام إلى النتيجة. رمز البايت الثنائي 11011 يساوي 27.

حركة الرقم XOR

حركة الرقم XOR يتم تمثيلها بالعلامة (\^)، بالطبع، وهي تعمل مباشرة على الشكل الثنائي. حركة XOR تختلف عن OR، حيث يعود 1 فقط عندما يكون هناك رقم واحد يحتوي على الرقم 1. جدول الحقيقة كالتالي:

الرقم في الرقم الأول الرقم في الرقم الثاني النتيجة
1 1 0
1 0 1
0 1 1
0 0 0

لحركة XOR بين 25 و 3، البرمجة كالتالي:

var iResult = 25 ^ 3;
alert(iResult);	//يظهر "26"

نتيجة حركة XOR بين 25 و 3 هي 26:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001
  3 = 0000 0000 0000 0000 0000 0000 0000 0011
---------------------------------------------
XOR = 0000 0000 0000 0000 0000 0000 0001 1010

من الواضح، في الرقمين، هناك 4 أرقام تحتوي على الرقم 1، وتُنقل هذه الأرقام إلى النتيجة. الرقم الثنائي 11010 يساوي 26.

حركة إلى اليسار الماركة المقدرة

حركة إلى اليسار الماركة المقدرة تعبر عنه بثلاثة علامات أقل (<<). إنه يحرك جميع الأرقام في الرقم إلى اليسار بكمية محددة. على سبيل المثال، إذا قمت بحركة الرقم 2 (يساوي 10 في النظام الثنائي) إلى اليسار 5 مرات، النتيجة ستكون 64 (يساوي 1000000 في النظام الثنائي):

var iOld = 2;		//يساوي 10 في النظام الثنائي
var iNew = iOld << 5;	//يساوي 1000000 في النظام الثنائي 64

ملاحظة:عند حركة الرقم إلى اليسار، يبقى 5 فراغات في نهاية الرقم. يتم استخدام حركة إلى اليسار لتعبئة هذه الفراغات بـ 0، مما يجعل النتيجة رقمًا كاملاً من 32 الرقم.

الرقم 2 يتم استبداله إلى اليسار

ملاحظة:حركة إلى اليسار تحافظ على إشارة الرقم. على سبيل المثال، إذا قمت بحركة -2 إلى اليسار 5 مرات، ستحصل على -64 وليس 64. "هل الإشارة تُخزن في الرقم 32؟" نعم، ولكن هذا يتم في الخلفية ECMAScript، والذي لا يمكن للبرمجة الوصول إليه مباشرة إلى الرقم 32. حتى إذا قمت بطباعة عدد سالب بشكل خطي، فإن العرض هو شكل الإشارة السلبية (مثل، -2 سيظهر -10).

عمودية الحركة إلى اليمين الماركة المقدرة

عمودية الحركة إلى اليمين الماركة المقدرة تعبر عنه بثلاثة علامات تساوي أكبر (>>). إنه يحرك جميع الأرقام في 32 الرقم إلى اليمين ككل، مع الحفاظ على الرقم نفسه (الإشارة الإيجابية أو السلبية). عمودية الحركة إلى اليمين هي عكس الحركة إلى اليسار. على سبيل المثال، عند حركة 64 إلى اليمين 5 مرات، تصبح 2:

var iOld = 64;		//يساوي 1000000 في الثنائي
var iNew = iOld >> 5;	//يساوي 10 في الثنائي، أي 2 في العددي

بالنسبة، بعد نقل الرقم، سيكون هناك فراغات. هذه المرة، الفراغات تكون في الجانب الأيسر من الرقم، ولكن بعد موقع الرمز الإشاري. يستخدم ECMAScript قيمة الرمز الإشاري لتعبئة هذه الفراغات، لإنشاء عدد كامل، كما هو موضح في الشكل التالي:

الرقم 64 يتم استبداله إلى اليمين مع إشارة

عمليات النقل الأيمن غير الموقوف

يتم تمثيل عمليات النقل الأيمن غير الموقوف بثلاثة علامات أكثر (>>>). إنه ينقل جميع أرقام الـ 32 بت للعدد غير الموقوف ككل. بالنسبة للعدد الإيجابي، النتيجة لعمليات النقل الأيمن غير الموقوف تشبه عملية النقل الأيمن الإشاري.

باستخدام مثال عملية النقل الأيمن الإشاري، إذا تم نقل 64 5 مرات إلى اليمين، سيصبح 2:

var iOld = 64;		//يساوي 1000000 في الثنائي
var iNew = iOld >>> 5;	//يساوي 10 في الثنائي، أي 2 في العددي

لكن الوضع مختلف بالنسبة للعدد السالب.

يتم تعبئة الفراغات باستخدام 0 في عمليات النقل الأيمن غير الموقوف. بالنسبة للعدد الإيجابي، فهذا يشبه عملية النقل الأيمن الإشاري، بينما يتم التعامل مع العدد السالب كعدد إيجابي.

بما أن النتيجة لعمليات النقل الأيمن غير الموقوف هي عدد صحيح من 32 بت، فإن النقل الأيمن غير الموقوف للعدد السالب ينتج دائمًا عدد كبير جدًا. على سبيل المثال، إذا تم نقل -64 5 مرات إلى اليمين، سيتم الحصول على 134217726. كيف يمكن الحصول على هذا الناتج؟

لتحقيق ذلك، يجب تحويل هذا الرقم إلى شكله غير الموقوف المتساوي (على الرغم من أن الرقم نفسه هو إشاري)، يمكن الحصول على هذا الشكل عبر الكود التالي:

var iUnsigned64 = -64 >>> 0;

ثم، باستخدام toString() من نوع Number للحصول على تمثيلاته الحقيقية للبيانات، ويستخدم الأساس 2:

alert(iUnsigned64.toString(2));

سيكون الناتج 11111111111111111111111111000000، وهو تعبير إشاري لعدد -64 في شكله الثنائي، ولكن هو يساوي عدد غير الموقوف 4294967232.

لذلك، يجب أن تكون حذرًا عند استخدام عمليات النقل الأيمن غير الموقوف.