AND و بیتی (&)، OR یا بیتی (|) و XOR یای منحصر بیتی (^)
عملگرهای بیتی محاسبات خود را در سطح بیت متغیرها انجام میدهند. این نوع عملگرها به حل طیف گستردهای از مشکلات متداول برنامهنویسی کمک میکنند.
بخش زیادی از مطالبی که در این پست راجع به محاسبات بیتی آمده، از آموزشی است که در اینجا قابلدسترس است.
عملگرهای بیتی در آردوینو:
“و” بیتی:
عملگر و بیتی در ++C تک امپرسند (&) است و بین دو عبارت از جنس integer قرار میگیرد. این عملگر مستقلاً روی تکتک بیتهای عملوندهایش طبق این قانون عمل میکند: اگر هر دو بیت ورودی یک بودند، خروجی یک میشود؛ وگرنه خروجی صفر است. یک راه دیگر بیان کردن این موضوع، مثال زیر است:
1 2 3 4 5 | 0 0 1 1 operand1 0 1 0 1 operand2 ---------- 0 0 0 1 (operand1 & operand2) - returned result // نتیجهی عملگر و بیتی |
در آردوینو نوع int، شانزده بیتی است؛ پس استفاده از عملگر & بین دو عبارت، باعث انجام 16 عمل AND همزمان خواهد شد. مثال در یک تکه کد:
1 2 3 4 | int a = 92; // in binary: 0000000001011100 int b = 101; // in binary: 0000000001100101 int c = a & b; // result: 0000000001000100, or 68 in decimal. //حاصل معادل عدد شصت و هشت دهدهی است. |
هر 16 بیت a و b با استفاده از عملگر AND پردازش و همهی 16 بیت حاصل در c ذخیره میشوند. حاصل، مقدار 01000100 باینری است که معادل عدد 68 دهدهی است.
یکی از معمولترین استفادههای “و” بیتی، انتخاب بیت یا بیتهایی خاص از یک مقدار integer است که عمل ماسک کردن (masking) نامیده میشود. برای مثال:
1 2 3 4 5 6 7 8 | Mask: 00001111 Value: 01010101 Result: 00000101 // هدف ما حفظ چهار بیت پایین و حذف چهار بیت بالا است. پس یک ماسک مناسب نوشته و بر روی // مقدار خود قرار میدهیم. int val=01010101; int mask=00001111; int res= val & mask; |
“یا” بیتی:
عملگر یا بیتی در ++C، نماد لوله عمودی | (پایپ) است. همانند عملگر &، این عملگر نیز مستقلاً روی تکتک بیتهای عملوندهایش عمل میکند؛ اما واضح است که کاری که انجام میدهد، از عمل & متفاوت است. حاصل عملگر OR دو بیت، در صورتی یک است که یکی یا هر دو بیت 1 باشند. وگرنه حاصل صفر میشود. به بیانی دیگر:
1 2 3 4 5 | 0 0 1 1 operand1 0 1 0 1 operand2 ---------- 0 1 1 1 (operand1 | operand2) - returned result // نتیجه عملگر یا بیتی |
مثالی از یا بیتی در تکه کدی از ++C:
1 2 3 4 | int a = 92; // in binary: 0000000001011100 int b = 101; // in binary: 0000000001100101 int c = a | b; // result: 0000000001111101, or 125 in decimal. // حاصل یا بیتی دو عملوند، معادل عدد صد و بیست و پنج دهدهی است. |
برنامهای مثالی برای آردوینو uno:
کاری معمول برای عملگرهای AND و OR کاری است که برنامهنویسان به آن خواندن- اصلاح- نوشتن (Read-Modify-Write) یک پورت میگویند. در میکروکنترلرها، پورت یک عدد 8 بیتی است که چیزی مربوط به شرایط پینها را بیان میکند. نوشتن روی پورت، همهی پینها را بهیکباره کنترل میکند.
PORTD یک ثابت توکار است که به وضعیت خروجی پینهای دیجیتال 0,1,2,3,4,5,6,7 اشاره دارد. اگر در یک موقعیت بیت، 1 وجود داشته باشد، آن بیت HIGH است. (پینها باید با دستور ()pinMode به صورت خروجی تعریف شوند.) پس اگر بنویسیم ;PORTD = B00110001 پینهای 0،4 و 5 را HIGH کردهایم. در این عمل نکتهای وجود دارد: ممکن است که ما وضعیت پینهای 0 و 1 را نیز تغییر داده باشیم؛ این دو پین برای ارتباطات سریال آردوینو استفاده میشوند؛ پس ما ممکن است که در ارتباط سریال مداخله کرده باشیم.
الگوریتم ما برای برنامه این است:
- PORTD را بیاورید و تنها بیتهایی که متناظر با پینهای دلخواهتان (پینهایی که میخواهید کنترل کنید.) هستند را پاک کنید. (با “و” بیتی)
- برای پینهای تحت کنترل، مقدار PORTD اصلاحشده را با مقدار جدید ترکیب کنید. (با “یا” بیتی)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | int i; // counter variable int j; void setup(){ DDRD = DDRD | B11111100; // set direction bits for pins 2 to 7, leave 0 and 1 untouched (xx | 00 == xx) // same as pinMode(pin, OUTPUT) for pins 2 to 7 Serial.begin(9600); } void loop(){ for (i=0; i<64; i++){ PORTD = PORTD & B00000011; // clear out bits 2 - 7, leave pins 0 and 1 untouched (xx & 11 == xx) j = (i << 2); // shift variable up to pins 2 - 7 - to avoid pins 0 and 1 PORTD = PORTD | j; // combine the port information with the new information for LED pins Serial.println(PORTD, BIN); // debug to show masking delay(100); } } |
“یای منحصر” بیتی (XOR):
یک عملگر کمی غیرمعمول در ++C است که به آن یای منحصر یا XOR (اکس اُر) بیتی گویند. عملگر یای منحصر بیتی با علامت ^ نوشته میشود. این عملگر بسیار شبیه به عملگر “یا” بیتی | است فقط هنگامیکه هر دو عملوند یک باشند هم نتیجهی 0 میدهد. در واقع نتیجهی این عملگر هنگامیکه دو عملوند مشابه داشته باشد، 0 و هنگامیکه عملوندها متفاوت باشند 1 میشود.
1 2 3 4 5 | 0 0 1 1 operand1 0 1 0 1 operand2 ---------- 0 1 1 0 (operand1 ^ operand2) - returned result // حاصل عملگر یای منحصر روی دو عملوند. |
یک مثال کد ساده:
1 2 3 4 | int x = 12; // binary: 1100 int y = 10; // binary: 1010 int z = x ^ y; // binary: 0110, or decimal 6 // عملگر یای منحصر روی دو عدد دهدهی و حاصل. |
معمولا از عملگر ^ برای تغییر وضعیت برخی از بیتهای یک عبارت صحیح (مثلا تغییر از 0 به 1 یا 1 به 0) استفاده میشود. در یک عملیات XOR اگر در بیت ماسک عدد 1 باشد، آن بیت معکوس شده؛ اگر 0 باشد، بیت معکوس نشده و همان مقدار باقی میماند. در زیر برنامهای را برای چشمک زدن پین دیجیتال 5 میبینید:
1 2 3 4 5 6 7 8 9 10 11 | // Blink_Pin_5 // demo for Exclusive OR void setup(){ DDRD = DDRD | B00100000; // پین دیجیتال پنج را به عنوان خروجی قرار میدهد. Serial.begin(9600); } void loop(){ PORTD = PORTD ^ B00100000; // بیت پنج را معکوس میکند و بقیه را تغییر نمیدهد. delay(100); } |