ترميز الأعداد *
في هذا الكتاب، الفصول المعلَّمة بنجمة * قراءات اختيارية. وإذا كان وقتك ضيقاً أو وجدتها صعبة، فيمكنك تجاوزها في البداية ثم العودة إليها بعد إتمام الفصول الأساسية.
التمثيل بالمقدار والإشارة ومتمم الواحد ومتمم الاثنين
في الجدول الوارد في القسم السابق، نجد أن جميع أنواع الأعداد الصحيحة تستطيع تمثيل عدد سالب واحد أكثر من الأعداد الموجبة. فمثلاً نطاق النوع byte هو . وهذه الظاهرة مخالفة للحدس، وسببها الكامن يكمن في تمثيلات المقدار والإشارة ومتمم الواحد ومتمم الاثنين.
أولاً، تجدر الإشارة إلى أن الأعداد تُخزَّن في الحواسيب على صورة «متمم الاثنين». وقبل تحليل أسباب ذلك، لنعرّف هذه المفاهيم الثلاثة أولاً.
- التمثيل بالمقدار والإشارة: نعامل أعلى بت في التمثيل الثنائي للعدد كبت إشارة، حيث يمثّل عدداً موجباً و عدداً سالباً، وتمثّل البتات المتبقية قيمة العدد.
- متمم الواحد: متمم الواحد لعدد موجب هو نفسه تمثيله بالمقدار والإشارة. أما العدد السالب، فيُحصل على متمم الواحد له بعكس جميع البتات عدا بت الإشارة في تمثيله بالمقدار والإشارة.
- متمم الاثنين: متمم الاثنين لعدد موجب هو نفسه تمثيله بالمقدار والإشارة. أما العدد السالب، فيُحصل على متمم الاثنين له بإضافة إلى متمم الواحد.
يوضح الشكل أدناه طرق التحويل بين المقدار والإشارة ومتمم الواحد ومتمم الاثنين.

التمثيل بالمقدار والإشارة، رغم كونه الأكثر بداهة، له بعض القيود. فمن جهة، لا يمكن استخدام تمثيل الأعداد السالبة بالمقدار والإشارة في العمليات مباشرةً. فمثلاً، حساب بالمقدار والإشارة ينتج ، وهو خطأ بيّن.
ولحل هذه المشكلة، أدخلت الحواسيب متمم الواحد. فإذا حوّلنا المقدار والإشارة أولاً إلى متمم الواحد، وحسبنا بمتمم الواحد، ثم أعدنا النتيجة إلى تمثيل المقدار والإشارة، أمكننا الحصول على النتيجة الصحيحة .
ومن جهة أخرى، لتمثيل العدد صفر بالمقدار والإشارة تمثيلان: و. وهذا يعني أن العدد صفر يقابل ترميزين ثنائيين مختلفين، مما قد يسبب غموضاً. فمثلاً، في الأحكام الشرطية، إذا لم نميّز بين الصفر الموجب والصفر السالب، فقد يؤدي ذلك إلى نتائج حكم غير صحيحة. وإذا أردنا معالجة الغموض بين الصفر الموجب والسالب، احتجنا إلى إدخال عمليات حكم إضافية، مما قد يقلل الكفاءة الحسابية للحاسوب.
وعلى غرار تمثيل المقدار والإشارة، يعاني متمم الواحد أيضاً من مشكلة غموض الصفر الموجب والسالب. لذلك أدخلت الحواسيب متمم الاثنين. ولنلاحظ أولاً عملية تحويل الصفر السالب من المقدار والإشارة إلى متمم الواحد ثم إلى متمم الاثنين:
إضافة إلى متمم الواحد للصفر السالب تولّد حمل (carry)، ولكن بما أن طول النوع byte هو 8 بتات فقط، فإن الذي يفيض إلى البت التاسع يُهمَل. أي إن متمم الاثنين للصفر السالب هو ، وهو نفسه متمم الاثنين للصفر الموجب. وهذا يعني أنه في تمثيل متمم الاثنين يوجد صفر واحد فقط، وبذلك يُحلّ غموض الصفر الموجب والسالب.
ويبقى سؤال أخير: نطاق النوع byte هو ، فمن أين يأتي العدد السالب الإضافي ؟ نلاحظ أن جميع الأعداد الصحيحة في الفترة لها تمثيلات مقابلة بالمقدار والإشارة ومتمم الواحد ومتمم الاثنين، ويمكن التحويل بين المقدار والإشارة ومتمم الاثنين.
غير أن متمم الاثنين استثناء، فليس له تمثيل مقابل بالمقدار والإشارة. وبحسب طريقة التحويل، نحصل على أن تمثيل هذا المتمم بالمقدار والإشارة هو . وهذا تناقض بيّن، لأن هذا التمثيل بالمقدار والإشارة يمثّل العدد ، وينبغي أن يكون متمم الاثنين له هو نفسه. وقد نصّت الحواسيب على أن متمم الاثنين الخاص يمثّل . وفي الواقع، فإن نتيجة حساب بمتمم الاثنين هي .
ربما لاحظت أن جميع الحسابات أعلاه عمليات جمع. وهذا يلمّح إلى حقيقة مهمة: صُمّمت دارات العتاد داخل الحواسيب أساساً على أساس عمليات الجمع. ويعود السبب إلى أن عمليات الجمع أبسط في التنفيذ على العتاد من العمليات الأخرى (مثل الضرب والقسمة والطرح)، وأسهل في التوازي، وأسرع في التنفيذ.
ويرجى ملاحظة أن هذا لا يعني أن الحواسيب لا تستطيع سوى الجمع. فبدمج الجمع مع بعض العمليات المنطقية الأساسية، تستطيع الحواسيب تنفيذ عمليات رياضية أخرى متنوعة. فمثلاً، يمكن تحويل حساب الطرح إلى حساب الجمع ؛ ويمكن تحويل حساب الضرب والقسمة إلى حساب عمليات جمع أو طرح متعددة.
يمكننا الآن تلخيص سبب استخدام الحواسيب لمتمم الاثنين: فبتمثيل متمم الاثنين، تستطيع الحواسيب استخدام الدارات والعمليات نفسها للتعامل مع جمع الأعداد الموجبة والسالبة، دون تصميم دارات عتاد خاصة للطرح أو معالجة غموض الصفر الموجب والسالب على حدة. وهذا يبسّط تصميم العتاد تبسيطاً كبيراً ويحسّن الكفاءة.
تصميم متمم الاثنين بالغ البراعة. ونظراً لضيق المساحة، نكتفي بهذا القدر. ونشجّع القراء المهتمين على الاستكشاف أكثر.
ترميز الأعداد العشرية العائمة
قد يلاحظ القارئ اليقظ أن int وfloat لهما الطول نفسه، فكلاهما 4 بايتات، لكن لماذا يكون نطاق float أكبر بكثير من نطاق int؟ هذا مخالف جداً للحدس، إذ من المنطقي أن float يحتاج إلى تمثيل الأعداد العشرية، فينبغي أن يكون نطاقه أصغر.
وفي الواقع، يعود السبب إلى أن العدد العشري العائم float يستخدم طريقة تمثيل مختلفة. ولنرمز إلى عدد ثنائي من 32 بتاً كما يلي:
وفقاً لمعيار IEEE 754، يتكوّن float ذو 32 بتاً من الأجزاء الثلاثة التالية.
- بت الإشارة : يشغل بتاً واحداً، ويقابل .
- بت الأُس : يشغل 8 بتات، ويقابل .
- بت الكسر : يشغل 23 بتاً، ويقابل .
وطريقة حساب القيمة المقابلة للعدد الثنائي float هي:
وبالتحويل إلى النظام العشري، تكون صيغة الحساب:
ونطاق كل مكوّن هو:

وبمراقبة الشكل أعلاه، بمعطى بيانات المثال و و، لدينا:
الآن يمكننا الإجابة عن السؤال الأول: يتضمن تمثيل float بت الأُس، مما يؤدي إلى نطاق أكبر بكثير من نطاق int. ووفقاً للحساب أعلاه، فإن أكبر عدد موجب يستطيع float تمثيله هو ، ويمكن الحصول على أصغر عدد سالب بتبديل بت الإشارة.
ورغم أن العدد العشري العائم float يوسّع النطاق، فأثره الجانبي التضحية بالدقة. فالنوع الصحيح int يستخدم جميع البتات الـ32 لتمثيل الأعداد، وتكون الأعداد موزّعة بالتساوي؛ أما بسبب وجود بت الأُس، فكلما كبرت قيمة العدد العشري العائم float، كبر الفرق بين عددين متجاورين عادةً.
وكما هو موضح في الجدول أدناه، لبتات الأُس و معانٍ خاصة، تُستخدم لتمثيل الصفر واللانهاية و وغيرها.
الجدول
| بت الأُس E | بت الكسر | بت الكسر | صيغة الحساب |
|---|---|---|---|
| عدد دون معياري | |||
| عدد معياري | عدد معياري | ||
ومن الجدير بالذكر أن الأعداد دون المعيارية تحسّن دقة الأعداد العشرية العائمة تحسيناً ملحوظاً. فأصغر عدد معياري موجب هو ، وأصغر عدد دون معياري موجب هو .
ويستخدم النوع المزدوج الدقة double أيضاً طريقة تمثيل مشابهة لـfloat، ولن نفصّلها هنا.