منشور

أنظمة العد وطرق التحويل بينها

لنتعرف على النظام الثنائي والنظام الثماني والست عشري. وطرق التحويل بينهم

أنظمة العد؟ ماهذا؟ جميعنا يعلم طريقة العد والحساب أليس كذلك؟ الحقيقة..ليس تمامًا! فجميعنا يستخدم نظامًا واحدًا في العد يُدعى النظام العَشري، ولكن هناك أنظمة أخرى للعد و لتمثيل الأعداد وحسابها، لنتعرف عليها: سنتحدث في هذه الفقرة عن أنظمةِ العدِ الأربعةِ التالية:

  • نظامُ العدِ العشري
  • نظام العد الثنائي
  • نظام العد الثماني
  • نظام العد الست عشري

محتويات الصفحة:

نظام العد العشري

بالإنجليزية Decimal System. ويتألف من الأعداد العشرية التي نستخدمها نحن في حياتنا اليومية، وتحوي الأرقام من 0 إلى 9، أي عشَرةُ أرقام، ولهذا نسميها الأعدادَ العشرية. من الأسبابِ المحتملةِ لاحتوائه على عشَرةِ أرقام هو استخدامُ الإنسان منذ القدم لأصابع يده العشْرِ في العد.

لاحظ معي لغويًا أن العدد (number) يمكن أن يتألف من عدة أرقام (أي خانات) مثل 135، أما الرقم (digit) فيتألف من خانة واحدة فقط ويكون أحدَ الأرقامِ العشَرة التي ذكرناها. وفي هذا السياق يكون استخدامُنا لغويًا لمصطلح “رقم الهاتف” استخدام خاطئ، والصحيح هو “أرقام الهاتف”.

يمكن تمثيل أي عدد في هذا النظام وفق التالي، فمثلًا إذا كان لدينا الرقم 54، فيمكن تمثيله بضرب الرقم في خانة العشرات بعشرة (أي عشرة أس واحد) وضرب الرقم في خانة الآحاد بواحد (أي عشرة أس صفر)، وجمع العددين معًا:

$$ \textcolor{blue}{54} = \textcolor{blue}{5} × 10^1 + \textcolor{blue}{4} × 10^0 $$

وهكذا ﻷي عدد نقوم بضرب كل رقم فيه بعشرة مرفوعة ﻷس خانة الرقم، ثم نجمع تلك الأعداد مع بعضها. لنأخذ مثالا آخرًا، حيث لدينا عددٌ مؤلفٌ من أربعةِ أرقام، أي أربعِ خانات يمكننا ترتيبها من صفر إلى ثلاثة، ثم ضرب كل رقم بعشرة مرفوعة ﻷس ترتيب الخانة:

$$ \textcolor{blue}{7389} = \textcolor{blue}{7} × 10^3 + \textcolor{blue}{3} × 10^2 + \textcolor{blue}{8} × 10^1 + \textcolor{blue}{9} × 10^0 $$

ويمكن تمثيل الأرقام ذات الفاصلة العشرية عبر استخدام الأس السالب للعدد عشرة، كما في المثال التالي:

$$ \textcolor{blue}{526,12} = \textcolor{blue}{5} × 10^2 + \textcolor{blue}{2} × 10^1 + \textcolor{blue}{6} × 10^0 + \textcolor{blue}{1} × 10^{-1} + \textcolor{blue}{2} × 10^{-2} $$

نظام العد الثنائي

“ينقسم الناس إلى 10، أولئك الذين يعرفون نظام العد الثنائي، والذين لا يعرفونه.”

بالإنجليزية Binary System. يتكون نظام العد الثنائي (وكما يتضح من اسمه) من رقمين فقط هما 0 و 1. يعمل الحاسوب بالكامل وفق نظام العد الثنائي هذا (وستتعلم كيفية ذلك بالتفصيل خلال هذا الكتاب إن شاء الله). حيث نحتاج لهذا النظام في الحاسوب بسبب سهولة تمثيله فيزيائيًا، فالتيار الكهربائي إما أن يمر أو لا يمر، أي إما واحد أو صفر، والضوء في الألياف الضوئية إما موجود أو غير موجود، أي إما واحد أو صفر مجددًا، وهكذا.

نسمي الرقم الذي يكون أحد هذين الرقمين فقط بالقيمة المنطقية، وتدعى بالإنجليزية Boolean value نسبة لعالم الرياضيات George Boole (1815 - 1864) الذي نشر كتاب “قوانين الفكر” The Laws of Thought عام 1854 والذي شكل أساسَ المنطق الذي بُني عليه الحاسوب لاحقًا. على الرغم من أن الأعداد الثنائية هذه موضوعة قبل ذلك التاريخ.

George_Boole George Boole (1815 - 1864)

قبل الدخول في تفاصيل هذا النظام، سنقم من الآن فصاعدًا وللتمييز بين الأعداد التابعة للأنظمة المختلفة بوضع لاحقة بعد العدد، والتي تكون dec (من decimal) أسفل الأعداد ذات النظام العشري، مثل \(105_{dec}\) و bin (من binary) أسفل الأعداد ذات النظام الثناثي، مثل \(110_{bin}\) علمًا أن بعض المراجع تستخدم الأساس بدلًا من الأحرف (هذه مثل \(105_{10}\) و \(110_{2}\) .) (حيث أساس النظام العشري هو 10 وأساس النظام الثنائي هو 2).

والآن، يمكن تمثيلُ هذه الأعداد في نظام العد العشري بطريقة مشابهة لما ذُكر سابقًا، إلا أننا نضرب هنا بـاثنين بدلًا من 10:

$$ \textcolor{blue}{1101}_{bin} = \textcolor{blue}{1} × 2^3 + \textcolor{blue}{1} × 2^2 + \textcolor{blue}{0} × 2^1 + \textcolor{blue}{1} × 2^0 = 8 + 4 + 0 + 1 = 13_{dec} $$

لاحظ كيف أن العدد هذا 1101 في نظام العد الثنائي يُمثِّل العدد 13 في نظام العد العشري، أي أن أنظمة العد هذه غير منفصلة عن بعضها، ويمكن تمثيل أي عدد من أي نظام بالأعداد المقابلة لها في الأنظمة الأخرى. كما يمكن هنا مجددًا تمثيل الأرقام بعد الفاصلة عبر الضرب بأس سالب

$$ \textcolor{blue}{1101.110} = \textcolor{blue}{1} × 2^3 + \textcolor{blue}{1} × 2^2 + \textcolor{blue}{0} × 2^1 + \textcolor{blue}{1} × 2^0 + \textcolor{blue}{1} × 2^{-1} + \textcolor{blue}{1} × 2^{-2} + \textcolor{blue}{0} × 2^{-3} = 13.75 $$

وكما تعلم، يمكن في الحسابات اليدوية تبسيط الأس السالب بجعله موجبًا في المقام. حيث لدينا هنا بعد الفاصلة العدد ½ أي 0.5 و ¼ أي 0.25 ومجموعهم ثلاثة أرباع أي 0.75

نظام العد الثماني

بالإنجليزية Octal System ويُلفظ اُُكتال. ويحوي ثمانية أرقام من 0 حتى 7، ويمكن تمثيله في النظام العشري بالضرب بالرقم ثمانية مرفوعًا ﻷس خانة الرقم:

$$ \textcolor{blue}{112}_{oct} = \textcolor{blue}{1} × 8^2 + \textcolor{blue}{1} × 8^1 + \textcolor{blue}{2} × 8^0 = 64 + 8 + 2 = 74_{dec} $$

عرفنا أن النظام العشري هو ما نستخدمه في حياتنا اليومية فهو أسهل لنا، وأن النظام الثنائي أسهل للحاسوب لسهولة تمثيله فيزيائيًا، ولكن لماذا وُضع هذا النظام؟ سؤال جميل، لقد قيل أن المتحدثين بلغة اليوكي (Yuki) في كالفيورنيا (تقع في أمريكا) استخدموا هذا النظام، فقد كانوا يَعدون الفراغات بين أصابع اليد بدلًا من الأصابع نفسها! واستُخدم كذلك في المكسيك بسبب استخدامهم في العد للمفاصل الثمانية لليد المغلقة.

نظام العد الثماني

علمًا أن العد في ذلك الوقت لم يكن يبدأ من الصفر، فالصفر بحد ذاته اختراع تم وضعه لاحقًا. لكننا هنا في علم الحاسوب نبدأ العد دائمًا من الصفر.

حسنًا.. ولكن ما هو استخدام نظام العد الثماني اليوم في الحاسوب؟

سؤال جميل أيضًا، للإجابة عليه دعنا نأخذ المعلومة التالية:

علمنا أن الأساس في نظام العد الثماني هو الرقم 8 وهذا يساوي \(2^3\) . يعني ذلك أن كل رقم في نظام العد الثماني يمثل ثلاثة أرقام في نظام العد الثنائي، وبعكس العبارة فكل ثلاثة أرقام في نظام العد الثنائي يمكن تمثيلها برقم واحد في نظام العد الثماني، لننظر قبل إعطاء مثال لكل الاحتمالات الممكنة لثلاث أرقام مجتمعة في النظام الثنائي (اقرأ الجدول من اليسار لليمين):

Octal Decimal توضيح 3-bit Binary Number
0 0 $0×2^2 + 0 × 2^1 + 0 × 2^0$ 000
1 1 $0×^2 + 0 × 2^1 + 1 × 2^0$ 001
2 2 $0×2^2 + 1 × 2^1 + 0 × 2^0$ 010
3 3 $0×2^2 + 1 × 2^1 + 1 × 2^0$ 011
4 4 $1×2^2 + 0 × 2^1 + 0 × 2^0$ 100
5 5 $1×2^2 + 0 × 2^1 + 1 × 2^0$ 101
6 6 $1×2^2 + 1 × 2^1 + 0 × 2^0$ 110
7 7 $1×2^2 + 1 × 2^1 + 1 × 2^0$ 111

وكما ترى، عندما يكون لدينا عدد ثنائي مؤلف من ثلاث أرقام فقط، فأعظم قيمة يمكن أن تكون هي (في السطر الأخير من الجدول) ثلاث واحدات والتي يقابلها الرقم 7 في نظامي العد العشري والثماني، وهو أعظم رقم في نظام العد الثماني، لذا يمكن في هذه الحالة (أي في حالة ثلاث أرقام من النظام الثنائي) تمثيل جميع القيم باستخدام رقم واحد فقط في نظام العد الثماني. فإذا كان لدينا العدد الثنائي التالي:

\[100101001010\]

فيمكن تحويله للنظام الثماني عبر تحويل كل ثلاثة أرقام بدءًا من اليمين:

010 001 101 100
2 1 5 4

ويكون أولُ ثلاثةِ أرقام تساوي 2، والتي تليها تساوي 1 ثم 5 ثم 4.

وبالتالي يكون العدد الثنائي المعطى مساوي للعدد التالي في النظام الثماني:

\[100101001010_{bin} = 4512_{oct}\]

لنأخذ مثالا آخرًا: يمكن في هذا العدد أن نأخذ ثلاثة أرقام ثم ثلاثة ثم ثلاثة ثم ينتج رقم وحيد، نُكمله لثلاثة أرقام عبر إضافة صفرين على يساره

\[1 010 111 100\]
100 111 010 001
4 5 2 1

وبهذا نجد أن نظام العد الثماني يقوم بتمثيل الأعداد الثنائية بشكل أبسط، خاصة عندما يكون لدينا أرقام ثنائية كثيرة، فيكون تحويلُها لأعداد ثمانية بمثابةِ تخفيضِ حجمِ الأعداد الثنائية إلى الثلث.

يُستخدم اليوم نظام العد هذا في بعض البرمجيات لاختصار الأعداد الثنائية التي تتألف من ثلاث أو ست أو تسع أرقام، مثل استخدامه في الأداة chmod (اخنصار لـ change mode ) على نظامي لينكس وماك لتحديد صلاحية الملفات والمجلدات.

حيث يمثل كلُ رقمٍ هنا ثلاثةَ أرقام من النظام الثنائي، والتي تمثلُ بدورها صلاحياتِ القراءة والكتابة وتنفيذ البرامج. حيث يمثل رقم 1 إعطاء الصلاحية و 0 منعها. تمثل أول ثلاثةِ أرقام الصلاحياتِ الثلاث هذه للمستخدم الحالي، والتي يليها للمجموعة التي يتبع لها المستخدم، والأخيرة لأيِ مستخدمٍ آخر.

111 111 111
Execute Write Read
others group user

يمكن مثلًا إعطاءُ صلاحيةِ القراءةِ فقط للمستخدمين الآخرين، وينتج عندها العدد التالي في النظام الثماني 774

وهكذا بدلأ من تحديد هذه الصلاحيات عبر كتابة تسعة أرقام في النظام الثنائي، نختزلها لثلاثة أرقام فقط من النظام الثماني.

نظام العد الست عشري

بالإنجليزية Hexadecimal System ويُلفظ هيكسا ديسيمال. ويتكون من 16 عنصرًا (أي $2^4$ )، وهم من 0 إلى 9، ثم من A إلى F، أي بالمجمل:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F

علمًا أنه لا فرق في كتابة الأحرف صغيرة كانت أم كبيرة.

يُظهر الجدول التالي الرموز الستة عشر لهذا النظام وما يقابله في النظام العشري:

Decimal Hexadecimal
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 A
11 B
12 C
13 D
14 E
15 F

يمكن تمثيل الأعداد هذه في النظام العشري بضربها بـ 16 مرفوعًا لأس خانة الرقم، ولكن الشيء الجديد هنا هو وجوب استبدال الأحرف بما يوازيها من أرقام.

\[\textcolor{blue}{15C}_{hex} = \textcolor{blue}{1} × 16^2 + \textcolor{blue}{5} × 16^1 + \textcolor{blue}{12} × 16^0 = 348_{dec}\]

رأينا في نظام العد الثماني كيف يمكن اختزال الأعداد الثنائية عبر تحويل كل ثلاثة أرقام لرقم من النظام الثماني، وهنا يمكن الاختزال أكثر عبر تحويل كل أربعة أرقام من الأعداد الثنائية إلى رقم من النظام الست عشري.

\[100101001010\]
1010 0100 1001
A 4 9
\[100101001010_{bin} = 94A_{hex}\]

ولنعلم هنا أن البت bit هو الرقم الواحد في النظام الثنائي، وأن البايت Byte يساوي 8 بت، وبهذا يمكن تمثيل البايت برقمين فقط في النظام الست عشري، كما في المثال التالي:

\[1101 0110\] \[D 6\]

وهذه ميزة مهمة في موضوع الاختصار. يستخدم هذا النظام بشكل واسع في معالجات اليوم وفي تمثيل الكثير من الأمور في الحاسوب والشبكات.

أحد طرق كتابة الأعداد في النظام الست عشري هو وضع السابقة 0x، فالعدد أعلاه مثلًا يمكن كتابته بالشكل:

\[0×94A\]

طريقة الكتابة هذه شائعة اليوم في أنظمة التشغيل ولغات البرمجة وتمثيل عناوين الذاكرة، كما سنرى لاحقًا.

– لم أفهم أهمية النظام الثماني. إذا كان هدفه اختصار الأعداد الثنائية، فالنظام العشري يختصرها أكثر كون أن أساسه 10 في حين أساس النظام الثماني 8.

نعم صحيح. في موضوع الاختصار يتم استخدام النظام الست عشري فلديه أكبر أساس وهو 16. أما النظام الثماني فلم يعد مُستخدم كثيرًا. ولكن إن كان لدينا عدد ثنائي من 6 خانات فقط، فاستخدام النظام الست عشري سيستهلك مساحة خانتين (2 بت) إضافيتين من الذاكرة، لذا يكون استخدام النظام الثماني أفضل. وهذا عمومًا ساري مع أي عدد ثنائي مؤلف من عدد خانات من مضاعفات الثلاثة.

تمارين

(تجد جميع الإجابات في آخر المقال)

  1. قم بتحويل العدد الثنائي التالي إلى عدد ست عشري

    \[1100 1011 1001\]
  2. قم بتحويل العدد الست عشري التالي إلى عدد عشري

    \[14FC\]
  3. قم بتحويل العدد الثنائي التالي إلى عدد ثماني

    \[100 110 101\]
  4. قم بتحويل العدد الثنائي التالي إلى عدد عشري

    \[1101\]
  5. قم بتحويل العدد الثماني التالي إلى عدد عشري

    \[123\]

التحويل بين أنظمة العد

لقد تعلمت للتو طرق التحويل من النظام الثنائي والثماني والست عشري للعشري، وكذلك التحويل من النظام الثنائي للثماني وللست عشري.

لنضع خريطة عامة للتحويل ونحدد ما تعلمناه إلى الآن

من /إلى الثنائي الثماني العشري الست عشري
الثنائي - ‫✓‬ ‫✓‬ ‫✓‬
الثماني   - ‫✓‬  
العشري     -  
الست عشري     ‫✓‬ -

ولنكمل الآن باقي طرق التحويل عبر الفقرة التالية:

سنتعلم في هذه الفقرة كيفية:

  • التحويل من النظام العشري (لباقي الأنظمة)
  • تحويل الأعداد بعد الفاصلة العشرية
  • التحويل غير المباشر

طريقة التحويل من النظام العشري

يوجد أكثر من طريقة للتحويل من النظام العشري لباقي الأنظمة، ولكن ربما الطريقة الأسهل والأكثر شيوعًا هي طريقة التقسيم، والتي بذاتها تحوي طريقتين فرعيتين، سأعطيك هنا الأسهل منهما أيضًا:

لدينا مثلا العدد 112 في النظام العشري ونريد تحويله للنظام الثنائي، سنقوم دائمًا بالتقسيم على 2 كونه الأساس للنظام الثنائي، وينتج العدد 56، ثم نكتب باقي القسمة (وهو إما أن يكون 1 في حال كان العدد فردي، أو 0 في حال كان العدد زوجي). ونستمر بالتقسيم إلى أن يصبح ناتج القسمة صفرًا:

باقي القسمة التقسيم
0 $112 / 2 = 56$
0 $56 / 2 = 28$
0 $28 / 2 = 14$
0 $14 / 2 = 7$
1 $7 / 2 = 3$
1 $3 / 2 = 1$
1 $1 / 2 = 0$

ننظر الآن لعمود باقي القسمة، ونكتب محتواه من الأسفل للأعلى، فينتج لنا العدد الثنائي المطلوب.

\[112_{dec} = 1110000_{bin}\]

تصلح هذه الطريقة مع أي أساس، فبدلًا من التقسيم على 2 للتحويل للنظام الثنائي يمكن التقسيم على 16 للتحويل للنظام الست عشري، والطريقة نفسها

باقي القسمة التقسيم
0 $112 / 16 = 7$
7 $7 / 16 = 0$
\[112_{dec} = 70_{hex}\]

لا تنسَ أننا نستمر في التقسيم إلى أن يصبح ناتج القسمة صفرًا لنأخذ مثالًا آخرًا مع عدد أكبر قليلًا، مثل العدد 2482:

باقي القسمة التقسيم
2 $2482 / 16 = 155$
11 = B $155 / 16 = 9$
9 $9 / 16 = 0$

وبالتالي:

\[2482_{dec} = 9B2_{hex} (0×9B2)\]

قد تسألني: وكيف عرفت باقي القسمة؟ يمكن ضبط بعض الآلات الحاسبة لإعطاء باقي القسمة، ويمكن بشكل يدوي التالي: حيث قمت أنا بتقسيم 2482 على 16 وظهر لي الناتج 155,125، هنا نأخذ العدد بعد الفاصلة ونضربه مجددًا بـ 16 فينتج باقي القسمة.

ويتم كذلك التحويل من النظام العشري للنظام الثماني بنفس الطريقة. حيث نقوم بالتقسيم على 8

باقي القسمة التقسيم
2 $2482 / 8 = 310$
6 $310 / 8 = 38$
6 $38 / 8 = 4$
4 $4 / 8 = 0$
\[2482_{dec} = 4662_{oct}\]

تحويل الفواصل العشرية

إذا كان لدينا العدد التالي 112,6875 في النظام العشري، فيمكن تحويله للنظام الثنائي مثلًا بنفس الطريقة التي تعلمناها، وذلك بالنسبة للعدد الذي قبل الفاصلة أي 112 في حالتنا هنا. وبعد ذلك نأخذ العدد الذي بعد الفاصلة أي 6875 في هذه الحالة، ونقوم هذه المرة بالضرب بدل التقسيم، ونتوقف عند الحصول على عدد صحيح أو عند الحصول على الدقة التي نريدها في حال كان العدد مابعد الفاصلة غير منتهي. لنحول 0.6875 للنظام الثنائي (فقد قمنا بتحويل 112 سابقا ونتج 1110000):

ماقبل الفاصلة الضرب
1 $0,6875 × 2 = 1,375$
0 $0,375 × 2 = 0,75$
1 $0,75 × 2 = 1,5$
1 $0,5 × 2 = 1,00$

لاحظ أننا دائمًا عند متابعة الضرب نأخذ فقط العدد بعد الفاصلة. نتج عدد صحيح وبالتالي نتوقف هنا، ونقرأ الناتج هذه المرة من الأعلى للأسفل. فيكون.

\[0,6875_{dec} = 0,1011_{bin}\]

لنأخذ مثالا آخرًا، حيث نجرب تحويل العدد 0.7514 من النظام العشري للثنائي:

ماقبل الفاصلة الضرب
1 $0,7514 × 2 = 1,5028$
1 $0,5028 × 2 = 1,0056$
0 $0,0056 × 2 = 0,0112$
0 $0,0112 × 2 = 0,0224$

نلاحظ هنا أننا لن نحصل على عدد صحيح مهما أكملنا، وبالتالي يمكن التوقف هنا عند أربعة أرقام (أو الاستمرار للدقة المطلوبة) ويكون الناتج هو:

\[0,7514_{dec} = 0,1100_{bin}\]

التحويل غير المباشر

لا يمكننا التحويل من النظام الست عشري مثلًا إلى النظام الثماني بشكل مباشر، ولهذا يتم استخدام الطريقةِ غير المباشرة في التحويل، حيث نقوم أولًا بالتحويل للنظام الثنائي، ومنه للنظام الثماني عبر أخذ كل ثلاثة أرقام من اليمين كما تعلمنا سابقًا.

ولكن كيف يتم التحويل من النظام الست عشري للثنائي؟ يمكن ذلك عبر تحويل كل رقم فيه إلى عدد من أربعة أرقام في النظام الثنائي. لننظر للجدول التالي والذي يُظهر الأعداد من 0 إلى 15 وتمثيلها في الأنظمة الأربعة.

Hexadecimal Octal Binary Decimal
0 0 0 0
1 1 1 1
2 2 10 2
3 3 11 3
4 4 100 4
5 5 101 5
6 6 110 6
7 7 111 7
8 10 1000 8
9 11 1001 9
A 12 1010 10
B 13 1011 11
C 14 1100 12
D 15 1101 13
E 16 1110 14
F 17 1111 15

ووفقًا للجدول والذي يحوي كل الأرقام الممكنة في النظام الست عشري، يمكن تحويل كل رقم ست عشري مباشرةً لما يقابله في الجدول من النظام الثنائي.

لنحول العدد 5E7 للنظام الثنائي، حيث نأخذ رقمًا رقمًا ونكتب مايقابله في النظام الثنائي وفق الجدول، إذا كان المقابل أقل من أربعة أرقام نضيف أصفارًا لليسار حتى نحصل على أربعة أرقام في النظام الثنائي.

\[5E7_{hex} = 0101 1110 0111_{bin}\]

يمكن طبعًا في النهاية التخلي عن الأصفار الموجودة على يسار كامل العدد، فهنا لدينا صفرًا واحدًا على اليسار يمكن التخلي عنه. بعد ذلك يمكن التحويل للنظام الثماني بتحويل كل ثلاثة أرقام بدءًا من اليمين، لنحول العدد الثنائي الناتج للنظام الثماني:

111 100 111 010
7 4 7 2
\[010111100111_{bin} = 2747_{oct}\]

كما يمكن التحويل من النظام الثماني للثنائي بنفس الطريقة، حيث يقابل كل رقم من العدد الثماني ثلاثة أرقام من العدد الثنائي. لنحول العدد 435 من الثماني للثنائي:

\[435_{oct} = 100 011 101_{bin}\]

وبهذا، إذا أردنا مثلًا التحويل من النظام الثماني للست عشري، فيمكن تحويل العدد من النظام الثماني للثنائي كما تعلمنا، ثم تحويل العدد الناتج من النظام الثنائي للست عشري عبر أخذ كل أربعة أرقام من اليمين كما تعلمنا أيضًا.

هل رأيت في آخر الفقرة كيف قمنا بالتحويل من النظام الثماني للثنائي، أي عبر تحويل رقم رقم؟ لا يمكن طبعًا فعل ذلك في التحويل من النظام العشري للثنائي. لماذا؟

لننظر مثلا للعدد 32، الرقم 3 هو 11 في النظام الثنائي، والرقم 2 هو 10 في النظام الثنائي، ولكن العدد العشري 32 لا يساوي للعدد الثنائي 1110. بل العدد 32 يساوي \(2^5\) وبالتالي فالعدد المقابل له في النظام الثنائي يجب أن يحوي واحدًا في الخانة السادسة (كون الخانة الأولى تمثل \(2^0\) )، ثم خمسة أًصفار على يساره، أي 100000.

ولكن يمكن التحويل مباشرة بالتفكير وفقًا لذلك (لمضاعفات العدد 2)، فمثلًا إذا أردنا تحويل العدد 17 من النظام العشري للثنائي، فنعلم أن أكبر عدد من مضاعفات العدد 2 والمحتوى داخل العدد 17 هو العدد 16، والذي يساوي 24، أي يكون لدينا واحد في الخانة الخامسة من العدد الثنائي:

$2^0$ $2^1$ $2^2$ $2^3$ $2^4$
        1

ثم يبقى لدينا واحدًا لنضيفه للـ 16 لنكمل للعدد 17، والواحد هو \(2^0\) ، أي أننا نضع واحدًا في الخانة الأولى من العدد الثنائي:

$2^0$ $2^1$ $2^2$ $2^3$ $2^4$
1       1

وكون الواحد في الخانة الخامسة تساوي 16 والواحد في الخانة الأولى تساوي 1، فأصبح لدينا 16+1 ويساوي 17، اكتمل لدينا العدد فتكون باقي الخانات أصفارًا:

$2^0$ $2^1$ $2^2$ $2^3$ $2^4$
1 0 0 0 1
\[17_{dec} = 10001_{bin}\]

وبنفس الطريقة إذا أردنا تحويل العدد 19 مثلًا، فهو عبارة عن 16 ( \(2^4\) ) زائد 2 ( \(2^1\) ) زائد 1 ( \(2^0\) )، أي واحدًا في الخانة الخامسة وواحدًا في الخانة الثانية وواحدًا في الخانة الأولى، والباقي أصفارًا، وهذا يعني 10011.

لا تنسَ أن الأصفار على يمين الأعداد الصحيحة لا يمكن الاستغناء عنها (1000)، وكذلك الأصفار على يسار الأعداد بعد الفاصلة (1,001).

أما الأصفار غير المهمة والتي لا معنى لها تكون على يسار العدد الصحيح (0001) وعلى يمين العدد بعد الفاصلة (1,100).

لاحظ أيضًا أن أكبر عدد يمكن أن يمثله العدد الثنائي ذو الخمس خانات هو عندما تكون جميع الخانات تحمل الرقم 1 أي 11111 والذي يساوي العدد 31 في النظام العشري (16+8+4+2+1)، وبالتالي لا يمكن تمثيل العدد 32 في خمس خانات، وسنحتاج لخانة سادسة.

وهذا يفيدنا في أنواع المتغيرات في البرمجة لاحقًا، والتي تحوي على عدد بتات (bits) محدد، والتي تمثل الخانات في العدد الثنائي. فإذا علمنا مثلًا أن العدد الصحيح في البرمجة (أي Integer) يتم إعطاؤه مساحة 32 بت فقط من الذاكرة، فنعلم وفقا لذلك أن أكبر قيمة يمكن أن يحويها لا تتجاوز 32 خانة في العدد الثنائي (وعندما يكون العدد الثنائي كله واحدات) وهو العدد 4294967295 في النظام العشري، وبالتالي لا يمكن للعدد التالي له أي 4294967296 أو الأعداد الأكبر من ذلك أن تتسع في الذاكرة المخصصة للعدد الصحيح.

يمكن استخدام الأداة التالية للتحويل تلقائيًا بين أنظمة العد الأربعة (للتأكد من حلولك): https://coderstoolbox.net/number

تمرين

أ. قم بتحويل العدد العشري التالي إلى عدد ثنائي (اكتفِ بخمس خانات بعد الفاصلة، وانتبه لكتابة فاصلة , وليس نقطة)

\[13,54\]

الكسور الدورية

رأينا سابقًا في أحد الأمثلة أنه عند تحويل العدد بعد الفاصلة العشرية من النظام العشري للثنائي، فقد ينتج عدد غير منتهي أو دوري (يكرر نفسه بشكل مستمر) في النظام الثنائي. لفهم ذلك أكثر دعنا نأخذ المثال التالي:

ماقبل الفاصلة الضرب
0 $0.1× 2 = 0,2$
0 $0.2 × 2 = 0.4$
0 $0.4 × 2 = 0.8$
1 $0.8 × 2 = 1,6$
1 $0,6 × 2 = 1,2$

ونلاحظ أن العدد بدأ بتكرار نفسه في السطر الأخير، وإذا أردنا الاستمرار فسنكرر السطر الثاني ومايليه وسيبقى الناتج يتكرر بنفس الشكل، لذا نسميه كسر دوري، ونضع خطًا فوق الجزء الذي يكرر نفسه من العدد بالشكل التالي:

\[0,1_{dec} = 0,0\overline{0011}_{bin}\]

وكما ترى فهناك العديد من الأعداد الكسرية (بعد الفاصلة) التي يمكن تمثيلها بعدد صحيح محدود في النظام العشري، ولكنها تكون طويلة جدًا ودورية في النظام الثنائي. وبما أن النظام الثنائي هو المستخدم في الحاسوب، يكون لهذه المشكلة تأثير كبير في البرمجة، وعلى المهندس المبرمج أن يعلم أنه عندما يعطي القيمة 0.1dec لمتغير ما، فستُحفظ هذه القيمة في الحاسوب بشكل مختلف، وستضيع الدقة في الحساب بمجرد حفظ القيمة وحتى قبل إجراء أي عملية حسابية عليها!

يمكن تجريب ذلك في كل لغات البرمجة، يُستخدم مثلًا في لغة بايثون إشارتي المساواة (==) للمقارنة بين عددين، فيمكن مثلًا المقارنة بين تساوي ناتج العملية 5+1 والعدد 6 والتي يجب أن تعطي True أي صح:

1
2
>>> 5+1 == 6
True

ولكن إذا جربنا المقارنة الثانية فستعطي خطأ (False)!

عدد دوري في لغات البرمجة

وقد عرفت السبب الآن.

يجب مراعاة هذا الموضوع كثيرًا، خاصة عند برمجة تطبيقات في مجالات حساسة، مثل التطبيقات المتعلقة بالبنوك وعمليات الدفع، والتطبيقات الخاصة بالأنظمة العسكرية والدفاعية، وغيرها..

أحد النتائج الكبيرة التي يمكن أن تسببها مثل هذه المشكلة، هو ما حدث عام 1991 في حرب الخليج حين أُطلقت صواريخ سكود (Scud) من العراق إلى الظهران، حيث فشلت مضادات الصواريخ الأمريكية باعتراض تلك الصواريخ بسبب احتوائها في برمجيتها على خطأ حسابي مثل الذي ذكرناه. وحيث تقوم مضادات الصواريخ برصد الصاروخ القادم في المرة الأولى، ثم وفق حسابات سليمة يجب أن ترصده مرة أخرى ضمن مساره الطبيعي لتطلق صاروخًا نحوه، ولكن الحسابات لم تكن سليمة، مما أدى لانحراف مجال تحديد الصاروخ في المرة الثانية وبالتالي عدم القدرة على رؤية الصاروخ القادم، وهذا أدى لتعطيل وظيفة مضادات الصواريخ بشكل كامل1.

ولقد علمتَ أن المشكلة الحسابية مازالت قائمة، على الرغم من تحسين الأنظمة الدفاعية وغيرها، إلا أن انعدام الدقة في مثل هذه الأعداد مازال قائمًا.

تجدر الإشارة لعدم وجود مشكلة في العملية العكسية، أي أن كل الكسور التي يمكن تمثيلها بعدد محدد منتهي في النظام الثنائي، يمكن تمثيلها أيضًا بعدد محدد منتهي في النظام العشري.

والآن..ما حل هذه المشكلة؟

كما ترى، فهناك كسور دورية في النظام العشري أيضًا مثل 1/3 والذي يعطي \(0.\overline{333}\) ويستمر الرقم ثلاثة إلى مالا نهاية، ولكن الحواسيب لا تفهم معنى الكسر الدوري، فهي أصلا تحوي مساحة محددة من الذاكرة لكل عدد، ولا يمكن لعدد ما أن يأخذ كل الذاكرة مثلًا بسبب التكرار هذا، مما يؤدي ﻷخطاء، فكلنا نعلم أن 1/3 + 1/3 + 1/3 يساوي 1، ولكن الحاسوب بسبب عدم فهمه للكسور الدورية سيرى 0.333 + 0.333 + 0.333 (ومهما كان عدد الأرقام بعد الفاصلة، سيبقى محدودا) وهذا سيُنتج 0.999 بدلا من 1. وإذا كنت تبرمج تطبيقًا للبنك فهذا سيبب كوارث، فإما سيقوم بإنقاص رصيد الزبون أو زيادته بسبب التقريب.

أحد الحلول المقترحة هو تجنب الأعداد الكسرية تمامًا، واستخدام أعداد صحيحة فقط، مثل استخدام متغيرات لحفظ العدد قبل الفاصلة ومتغيرات أخرى لحفظ العدد بعد الفاصلة بصفته عدد صحيح، أو حفظ العدد الكسري بصفته عدد صحيح، ففي التطبيق البنكي بدلًا من حفظ رصيد الزبون على أنه

$2.5152

مثلا، يمكن حفظه على أنه عدد صحيح

$25152

ويمكن في نهاية المطاف لعرض الناتج التقسيم على 10000 مثلًا للحصول على العدد الكسري، ونكون بذلك تجنبنا كل هذه المشاكل.

حل مقترح آخر هو تجنب الكسور التي تعطي ناتجًا غير مكتمل في النظام الثنائي تحديدًا. ولكن كيف نعرف هذه الأعداد التي تكون دورية في النظام الثنائي؟

تقول القاعدة العامة أنه يمكن تمثيل العدد الكسري p/q بشكل مكتمل غير دوري في نظام العد الذي يكون أساسه B، وحيث gcd(p, q) = 1، عندما تكون كل العوامل الأولية لـ q عوامل أولية لـ B أيضًا.

ألم تفهم شيئًا؟ وهو المطلوب :)

في البداية، تعني العبارة gcd(p, q) = 1 أن القاسم المشترك الأكبر للبسط والمقام هي الواحد، هذا يعني أن البسط غير قابل للقسمة على المقام، وإلا فسينتج عدد صحيح ولن يكون عدد كسري أصلًا.

يكون الأساس B كما تعلم 10 في نظام العد العشري و2 في النظام الثنائي وهكذا. العامل الأولي هو العدد الأولي الذي يكون أصغر من العدد المعطى أي محتوى فيه، ويمكنه تقسيم ذلك العدد. العدد \(10_{dec}\) مثلًا يحوي الأعداد الأولية 2 و 3 و 5 و 7 ولكنه يقبل القسمة على 2 و 5 فقط من هؤلاء، لذا فالعوامل الأولية للعدد 10 هي 2 و 5. وبالتالي يجب أن تكون الأعداد الأولية المحتواة في المقام q وتقسمه، محتواة في الأساس B وتقسمه أيضًا. والآن أعد قراءة القاعدة أعلاه ثم انظر للأمثلة التالية:

العدد 3 (عامل أولي للمقام) ليس عامل أولي للأساس 10 $1/3 = 0.333…_{dec}$
العدد 3 ليس عامل أولي للأساس 2 $1/3 = 0,010101…_{bin}$
العدد 3 عامل أولي للأساس 3 (إذا فرضنا نظام عد بهذا الأساس) $1/3 = 0,1_{3}$
العوامل الأولية هي نفسها 2 و 5 لكلا المقام والأساس (المتطابقَين أصلا) $1/10 = 0,1_{dec}$
العدد 5 ليس عاملا أوليا للأساس 2 $1/10 = 0,000110011…_{bin}$

يمكن الحصول كذلك على دقة أفضل في حساب الأعداد الكسرية باستخدام تمثيل آخر للأعداد، مثل تمثيل الفاصلة العشرية وفق BCD-Code أو معيار IEEE 754. سأشرح لك الأخير في مقال لاحق إن شاء الله.

حلول التمارين

  1. CB9
  2. 5372
  3. 465
  4. 13
  5. 83

أ. 1101,10001

الدرس التالي: العمليات الحسابية على الأعداد الثنائية

ولتمارين أكثر، يمكنك الاطلاع على المقال: أمثلة في أنظمة العد

هذا المنشور تحت ترخيص CC BY 4.0 بواسطة المؤلف.