الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

تعين الخيارات بواسطة تقنية Bitmask

مغلق
بدأه ♥ حُوريّة ♥ في 23 ديسمبر 2007 · 2 رد · 2,129 مشاهدة · في المواضيع والدروس
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم:

قبل البدء: من لديها | لديه الخبرة و الاساسيات حول الاعداد الثنائية والعمليات عليها يقوم بالإنتقال مباشرة إلى العنوان (مفهوم قناع الخانات الثنائية BITMASK) مباشرة.

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

 dialog_box = RESIZEABLE | CLOSE | OK | CANCEL;

و اللي هو عبارة عن تعيين خيارات مناسبة لمربع حوار ما. هذه الخيارات هي أن تكون النافذة قابلة للتغير الحجم وتحتوي على زرارات الإغلاق و الموافقة و الإلغاء.

كنت حابة اتعرف على ما يجري خلف الكواليس و علاقة المؤثر (|) بهذه الثوابت وكيفية تعرف البرنامج على الخيارات المنتقاة بواسطتي. في النهاية طلع اسم هذه الطريقة قناع الخانات الثنائية BITMASK. (ماني عارفة لو ترجمتي صحيحة لكن هذي اقرب ترجمة للمصطلح هذا.)

الموضوع هو عبارة عن توضيح فكرة قناع الخانات الثنائية BITMASK و مدى ارتباطها بالمؤثرات الثنائية Bitwise Operators اللي هم (| وَ &) و نسميهم (أو , و) على التوالي. تحديداً, فإن المفهوم والفكرة اللي انا مجتهدة في توصليها لكم هي كيف يتم تعيين الخيارات و كيف يتعرف البرنامج على هذه الخيارات المنتقاة بواسطة BITMASK و المؤثرات (| وَ &).

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

النظام الثنائي هو النظام الذي له القاعدة 2. بعكس النظام العشري والذي قاعدته العدد 10. نحن نتعامل مع النظام العشري بشتى مجالات الحياة, لكن الكمبيوتر يتعامل بالنظام الثنائي. شوفوا طقم الأعداد التالي و الذي يتكون منه نظامنا العشري المعتاد:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9

الآن نشوف طقم الأعداد اللي يتكون منها النظام الثنائي.

0, 1

لاحظوا أنه كل نظام و ليكن B يتكون من طقم الأعداد 0 إلى B-1. شوفوا طقم النظام العشري من صفر لحد عشرة ناقص واحد و اللي هو العدد 9. وكذلك تأملوا طقم النظام الثنائي و اللي هو من 0 لحد العدد 1. بالطبع, الكمبيوتر يتعامل مع العددين هذه بس ( 0, 1), ويمكننا بواسطة الأعداد الثنائية هذي تمثيل أي قيمة داخل الكمبيوتر و أيضاً تطبيق جميع العمليات الثنائية عليها, بالضبط مثل اللي رح نتعرف عليها قريباً و هي (| وَ &).

أوكي, نشوف الآن تمثيل للعدد 4 بواسطة النظام الثنائي داخل الكمبيوتر كالتالي: 100. و عشان تتأكدوا بأنها 4 حولوا هذا التمثيل من الثنائي إلى العشري بالطريقة التالية:

- نأخذ قيمة الخانة الموجودة بأقصى اليسار و نضربها في القاعدة 2 و نجمع الخانة التي تليها مع حاصل الضرب هذا.

- ثم نأخذ الناتج ونضربه في القاعدة 2 و نجمعه مع الخانة المباشرة التي لم نأخذها بعد.. و هكذا حتى نصل إلى آخر خانة موجودة بأقصى اليمين و نتوقف. بالضبط كما في المثال التالي:

100 = 1 * 2 + 0 -> 2 * 2 + 0 -> 4

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

لمحة سريعة على عمل المؤثرات | وَ & على الأعداد الثنائية:

تحتوي لغة c++ على ستة مؤثرات تتعامل مباشرة و بتحيز مع البيانات الثنائية وهي كالتالي:

 | & ^ ~ << >>

من مميزات هذه المؤثرات هي أنها تتعامل مع كل خانة من خانات العدد الثنائي بشكل منفرد. ما يهمنا في هذا الموضوع هما المؤثران | وَ &. و سنرى مثالين لكل واحد منهما في هذا الاقسم. بإمكانكم القيام بالبحث بخصوص العمليات الاربع الثنائية الأخرى من أي مصدر آخر.

اوكي, إن عمل المؤثر | و الذي يُدعى (أو Or) هو القيام بتعيين الحالة set state في الخانة الثنائية إلى واحد في حالة لو كان واحد على الأقل من الخانات له القيمة 1 (ركزوا على كلمة على الاقل), و غير ذلك فهو 0.

(طبعاً سنكتب التمثيل الثنائي للعدد مكون من 8 خانات Byte والتعويض بالصفر في خانات اقصى اليسار للعدد) مثل العدد 4 الذي تناولناه بالأعلى سيكون 00100 0000 مخزن في بايت داخل الكمبيوتر.

الآن نقوم بالتعامل مع العدد 4 0100 0000 و العدد 2 0010 0000 بواسطة المؤثر | لنتعرف على طريقة عمله بشكل عملي:

0000 0100

0000 0010

--------------

0000 0110

Another example 

0000 1000

0000 1000

--------------

0000 1000

نلاحظ كما لو كنا نقوم بعملية جمع للخانات في النظام العشري المعتاد, بأن 0 | 0 = 0 , 1 | 1 = 1 , 1 | 0 = 1. لا يهمنا الترتيب هنا على الإطلاق حيث أن 1 | 0 = 1 و 0 | 1 = 1 لأن المؤثر | Or له الخاصية الإبدالية Commutative Property مثل الجمع العادي بالضبط. من المثال الأول قام المؤثر | بين العدد 4 و 2 بإنتاج القيمة 0110 0000 و هي 6. و المثال الذي يليه و هو العدد 8 مع العدد 8 باستخدام المؤثر | انتج العدد 8 1000 0000 ايضاً و ذلك بالتعامل مع الاعداد الثنائية خانة تلو الأخرى كما في تعريف المؤثرات الثنائية السابق و هي ميزة من مميزات هذه المؤثرات على الأعداد.

الآن نتناول المؤثر & و الذي يقوم بالمقارنة بين الخانات الثنائية فإذا كانت كلها 1 يعطي الناتج 1 و غير ذلك فالناتج 0. نأخذ نفس الامثلة السابقة للنتعرف على عمل المؤثر & and:

0000 0100

0000 0010

--------------

0000 0000 

Another example 

0000 1000

0000 1000

--------------

0000 1000

لاحظوا أن هذا المؤثر لا يعطي القيمة 1 إلى إذا و فقط إذا كانت جميع الخانات أو المدخلات لها القيمة 1.

مفهوم قناع الخانات الثنائية BITMASK:

قناع الخانات الثنائية عبارة عن طريقة لضغط المعلومات المتعلقة بخيارات و سمات (ميزات) نظام ما. و هذه الطريقة جيدة بالتحديد إذا كانت هذه الخيارات والسمات محدودة. هذه الخيارات (السمات) تكون مخزنة على شكل ثوابت عددية, و قيمة كل منها هو قيمة مختلفة لقوى العدد 2 يعني 2N. هذا يعني 1, 2, 4, 8, 16, 32… وهي قيم العدد 2 مرفوعة للقوى من 0 إلى ما شاء الله, و لكن لا تنسوا أن هذه الطريقة نافعة في حالة إذا كان هناك خيارات وسمات محدودة يتميز بها ذلك النظام.

أولا هناك ميزة تميز هذه الاعداد (نواتج قوى العدد 2 "2N") عن الاعداد المنتظمة المعروفة 1 2 3 4 5 6 ... بأنها حتماً تنتج قيمة فريدة عند جمعها مع بعض البعض. على سبيل المثال. لا حظوا في الاعداد المنتظمة لو جمعنا 1 + 2 + 4 = 7, و 2 + 5 ايضاً = 7. لكن لاحظوا أننا لو قمنا بهذه العملية بكل الاشكال مع اعداد قوى العدد 2 فإننا حتماً سنحصل على ناتج فريد عن النواتج الأخرى. المربع التالي يسرد نواتج قوى العدد 2 ( من 20 إلى 232):

1   2   4   8   16   32   64   128   256   512   1024   2048   4096   8192   16384   32768   65536   131072   262144   524288   1048576   2097152   4194304   8388608   16777216   33554432   67108864   134217728   268435456   536870912   1073741824   2147483648

والمصادفة الجميلة هنا أن المؤثر الثنائي | يقوم بهذه العملية مع هذه الاعداد (قوى 2) بالضبط مثل مؤثر الجمع المعروف (+) مع الاعداد العشرية. و يعطي نواتج فريدة عند تعامله مع هذه الاعداد (قوى 2) وكأنها يقوم بجمعها مثل عملية الجمع. اوكي, لنتأكد من المثال التالي:

2 | 4 = 6 بالضبط مثل 2 + 4 = 6. لاحظوا إن العددان 2 و 4 من الاعداد الناتجة عن قوى العدد 2.

والمصادفة الأجمل أن المؤثر & يقوم بتحدد عما لو كان العدد المقارن مع الناتج هو من ضمن مكوناته الحسابية أو لا مثلا: 4 & 6 = 4 و 2 & 6 = 2 لكن 1 & 6 = 0 و هذا يعني أن العدد 1 ليس من أحد المكونات التي نتج عنها العدد 6 بواسطة المؤثر |. حاولوا التجربة بواسطة تحويل الاعداد السابقة 2 و 4 و 6 إلى تمثيل ثنائي وشاهدوا العملية ثنائية عشان تحققوا نتيجة أكبر في الفهم. مثل 2 0010 و 4 0100 بواسطة المؤثر | ينتج 6 0110 كما في المثال التالي:

 

0010

0100
-------

0110

انا معتمدة عليكم الآن تجربوا مؤثر & بين العدد 6 و 2 ثنائياً وتشوفوا الناتج على الورقة. و تحاولوا تتطبقوا المفهوم هذا على العدد 16 | 8 | 2 و من ثم احصلوا على الناتج و استخدموا المؤثر & مع أحد مكونات وشوفوا الناتج؟

اوكي إذا قناع الخانات الثنائية BITMASK في أمثلتنا هذي هو حزمة ثوابت أعداد القوى 2 مترابطة باستخدام المؤثر | مثل ( 2 | 4 | 16 | 64 | ).

تمثيل هذا المفهوم بواسطة لغة c++:

أنا أول ما اتعلمت هذه اللغة حبيت مفهوم العداد enumration كثير, ماكنت عارفة السبب. لكن الآن اكتشفت بأنه أداة سهلة جداً لجمع قيم ثابتة في حزمة معينة و إعطائها اسماء مناسبة تسهل عملية كتابة وفهم البرنامج. وطبعاً انا مستخدمته في المثال التالي لضم الثوابت والخيارات المتعلقة بالنظام.

الآن قمت بكتابة برنامج بسيط جداً. عبارة عن برنامج يقوم بطباعة خيارات الأخوات ( فاطمة, أمل, مرام, زهرة, وأنا) حول نكهات الآيس كريم المحببة لديهم من خيارات ثابتة ومحزومة داخل enum و مقيمة بواسطة قوى العدد 2. هذه الخيارات كالتالي:

 

VANILLA : فانيلا

CHOCOLATE : شوكليت

CARAMEL :كاراميل

STRAWBERRY : فراولة

NUTS : جوز(بندق)

PISTACHIO : فستق

ALL : جميع ما سبق

اللي انا ابغاكم تركزوا عليه هو إن القيم لهذه الثوابت هي قيم قوى العدد 2 من الأس 0 لحدة الأس 6 يعني القيم التالي على التوالي (1, 2, 4, 8, 16, 32): و تركزوا على كيفية طريقة تعيين الخيارات بواسطة هذه الثوابت مع المؤثر | كاقتراح عند نداء الإجراء setOptions لطلب و ذوق كل بنت مننا.

//The concept of the BITMASK.
/*
Authored by Raghad: to illustrate the Bitwize |, & (and,or)
operators and the BITMASK concept.
*/
#include <iostream>
using std::cout;
using std::endl;

//The IC-OPTIONS enum holds the Ic-cream Options.
enum IC_OPTIONS
{
	VANILLA = 1,
	CHOCOLATE = 2,
	CARAMEL = 4,
	STRAWBERRY = 8,
	NUTS = 16,
	PISTACHIO = 32,
	ALL = 64	 
};

void setOptions(unsigned int);

int main()
{
	cout << "Fatemah choice:" << endl;
	setOptions(CARAMEL | PISTACHIO | VANILLA);

	cout << "Amal choice:" << endl;
	setOptions(ALL);

	cout << "Maram choice:" << endl;
	setOptions(STRAWBERRY|VANILLA);

	cout << "Zahrh choice:" << endl;
	setOptions(VANILLA | CHOCOLATE | CARAMEL | PISTACHIO);

	cout << "Raghad choice:" << endl;
	setOptions(PISTACHIO | NUTS | VANILLA);


 return 0;
}

void setOptions(unsigned int bitmask)
{
	cout << "Ic-cream with the following flavor(s):\n";

	//Check if an individual option constructs the
	//BITMASK or not using the bitwise and & operator.

	if (bitmask & VANILLA)
		cout << "- Vanilla" << endl;
	if (bitmask & CHOCOLATE)
		cout << "- Chocolate" << endl;
	if (bitmask & CARAMEL)
		cout << "- Caramel" << endl;
	if (bitmask & STRAWBERRY)
		cout << "- Strawberry" << endl;
	if (bitmask & NUTS)
		cout << "- Nuts" << endl;
	if (bitmask & PISTACHIO)
		cout << "- Pistachio" << endl;
	if (bitmask & ALL)
		cout << "- All of the flavors sorts" << endl;

	cout << endl;
}

بعدين لاحظوا داخل الإجراء setOption وكيفية التحقق من لو كان قيمة أحد الخيارات هذه من أحد مكونات الـ BITMASK الممرر إلى الإجراء أو لا. و هذا بواسطة المؤثر & .

انا قررت اقدم البرنامج بشكل مبسط عشان الفهم يكون اسهل. و ان شاء الله يكون الموضوع مفيد والله ولي التوفيق.

تم تعديل هذه المشاركة بواسطة رغـــــــــد في 23 ديسمبر 2007 في 09:35

[وسط]

♥ Countess ♥

57899411.gif

♥

[/وسط]

#2

موضوع قيم شكرا لكي اختى على مجهودك.

واتمنى ان نرى المزيد والمفيد.

tvquran_6.gif

#3

ماشاء الله أختي العزيزة ,

بارك الله في مجهودك, الدرس جميل جداً,

سيتم تثبيثه لمدة يومين على الأقل حتى يتم التفاعل معه :happy:

تحياتي ,,

هذا الموضوع مغلق.

مواضيع مشابهة