تحويل الأعداد من النظام الثنائي إلى النظام السداسي عشر

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

النظام الثنائي Binary: يعتمد هذا النظام على الأساس 2 ؛ وتمثّل الأعداد نتيجة لذلك باستخدام رمزين فقط هما 0 و 1.

النظام السداسي عشر Hexadecimal: النظام السداسي عشر هو نظام أعداد موقعي يكون فيه الجذر أو الأساس هو 16 ويستخدم 16 رمزًا لتمثيل الأرقام. تستخدم الأرقام ‎0-9‎ لتمثيل نفسها، أما الأرقام ‎10-15 فتمثّل بواسطة الحروف A-F.

الطريقة الأولى

تتبع هذه الطريقة الخطوات التالية في تحويل العدد الثنائي المعطى إلى النظام السداس عشر:

  1. يقسّم العدد الثنائي المعطى إلى مجموعات تضمّ كل واحدة منها 4 بتات. تقسّم المجموعات من اليسار إلى اليمين قبل النقطة الفاصلة (إن وجدت) ومن اليمين إلى اليسار بعد النقطة الفاصلة (إن وجدت).
  2. حساب طول السلسلتين الفرعيتين اليمنى واليسرى بالنسبة إلى النقطة الفاصلة (ليكونا left_len و right_len).
  3. إن لم يكن طول السلسلة الفرعية left_len من مضاعفات العدد 4؛ أيّ أنّه ليس بالإمكان إنشاء مجموعات مكوّنة من 4 بتات، يُضاف أقل عدد ممكن من الأصفار إلى بداية السلسلة النصية الفرعية لجعل طولها من مضاعفات العدد 4.
  4. تُضاف الأصفار بنفس الطريقة إلى السلسلة الفرعية اليمنى إن لم يكن طولها من مضاعفات العدد 4، ويُضاف أقل عدد ممكن من الأصفار إلى نهاية السلسلة النصية الفرعية اليمنى لجعل طولها من مضاعفات العدد 4.
  5. استخراج المجموعات واحدة تلو الأخرى من جهة اليسار ثم إضافة القيمة المقابلة لها في النظام السداسي عشر.
  6. في حال وجود نقطة فاصلة في العدد المعطى فإنّها تُضاف إلى النتيجة في نفس مكانها.

تنفيذ الخوارزمية

تعرض الأمثلة التالية طريقة تنفيذ الخوارزمية في عدد من لغات البرمجة:

#include <bits/stdc++.h> 
using namespace std; 

// تنشئ الدالة روابطة بين الأعداد الثنائية
// وما يقابلها في النظام السداسي عشر
void createMap(unordered_map<string, char> *um) 
{ 
	(*um)["0000"] = '0'; 
	(*um)["0001"] = '1'; 
	(*um)["0010"] = '2'; 
	(*um)["0011"] = '3'; 
	(*um)["0100"] = '4'; 
	(*um)["0101"] = '5'; 
	(*um)["0110"] = '6'; 
	(*um)["0111"] = '7'; 
	(*um)["1000"] = '8'; 
	(*um)["1001"] = '9'; 
	(*um)["1010"] = 'A'; 
	(*um)["1011"] = 'B'; 
	(*um)["1100"] = 'C'; 
	(*um)["1101"] = 'D'; 
	(*um)["1110"] = 'E'; 
	(*um)["1111"] = 'F'; 
} 

// تحوّل الدالة العدد المعطى من النظام الثنائي إلى النظام السداسي عشر
string convertBinToHex(string bin) 
{ 
	int l = bin.size(); 
	int t = bin.find_first_of('.'); 
	
	// طول السلسلة الفرعية قبل النقطة الفاصلة
	int len_left = t != -1 ? t : l; 
	
	// إضافة أقل عدد من الأصفار إلى بداية السلسلة الفرعية اليسرى
	// لجعل طولها من مضاعفات العدد 4
	for (int i = 1; i <= (4 - len_left % 4) % 4; i++) 
		bin = '0' + bin; 
	
	// إن كانت هناك نقطة فاصلة
	if (t != -1)	 
	{ 
		// طول السلسلة النصية الفرعية بعد الفاصلة
		int len_right = l - len_left - 1; 
		
		// إضافة أقل عدد من الأصفار إلى نهاية السلسلة الفرعية اليمنى
		// لجعل طولها من مضاعفات العدد 4
		for (int i = 1; i <= (4 - len_right % 4) % 4; i++) 
			bin = bin + '0'; 
	} 
	
	// إنشاء روبط بين العدد الثنائي
	// والعدد الذي يقابله في النظام السداسي عشر
	unordered_map<string, char> bin_hex_map; 
	createMap(&bin_hex_map); 
	
	int i = 0; 
	string hex = ""; 
	
	while (1) 
	{ 
		// استخراج السلاسل النصية واحدة تلو الأخرى من جهة اليسار
		// يجب أن تحتوي كل سلسلة مستخرجة على 4 بتات
		// يُضاف العدد السداسي العشر المقابل للسلسلة المستخرجة إلى النتائج
		hex += bin_hex_map[bin.substr(i, 4)]; 
		i += 4; 
		if (i == bin.size()) 
			break; 
			
		// تضاف النقطة الفاصلة (إن وجدت) في مكانها الصحيح في النتيجة
		if (bin.at(i) == '.')	 
		{ 
			hex += '.'; 
			i++; 
		} 
	} 
	
	return hex;	 
} 

// اختبار الدالة السابقة
int main() 
{ 
	string bin = "1111001010010100001.010110110011011"; 
	cout << "Hexadecimal number = "
		<< convertBinToHex(bin); 
	return 0;	 
}

تعطي الشيفرات السابقة المخرجات التالية:

Hexadecimal number = 794A1.5B36

التعقيد الزمني

يبلغ التعقيد الزمني لهذه الخوارزمية المقدار O(n)‎، وتمثّل n طول السلسلة النصية المدخلة.

الطريقة الثانية

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

مصادر