יסודות התכנות בשפת C#‎ · פרק 10 — פעולות בוליאניות על סיביות ובסיסי ספירה⌂📚🏠
פרק 10

פעולות בוליאניות על סיביות ובסיסי ספירה

10.1 מבוא

כפי שלמדנו, יש טיפוס נתונים בשם byte, והוא קטן מ-int, שכן הוא יכול להכיל מספר שלם בתחום שבין 0 ל-255, כולל האפס וכולל המספר 255.

בפרק זה נטפל לפעמים ב-byte, בשל הקלות שבטיפול במספר קטן של סיביות, שכן משתנה מטיפוס byte נשמר בזיכרון ב-8 סיביות (8 bit), וה-byte נחשב יחידת זיכרון קטנה, ואילו נתונים מטיפוס int נשמרים בזיכרון ב-32 סיביות.

דוגמה 10.1
שימוש ב-byte וב-int
static void Main(string[] args)
{
  int x = 98;
  byte y = 98;
  Console.WriteLine("x={0}", x);
  Console.WriteLine("y={0}", y);
  x++;
  y++;
  Console.WriteLine("*************");
  Console.WriteLine("x={0}",x);
  Console.WriteLine("y={0}",y);
}
Microsoft Visual Studio Debug Console
x=98
y=98
*************
x=99
y=99
intx=98;00000000110001031302928...9876543210x=99;00000000110001131302928...9876543210bytey=98;0110001076543210y=99;0110001176543210

כל סיבית יכולה להכיל בזיכרון 1 או 0, מפני שהמספרים נשמרים בבסיס הבינארי.

דוגמה 10.2
int n = 270; ➔ 100001110

מספר זה נשמר ב-int, וסיביות אלה הן ה-LSB מתוך 32 הסיביות (נשמרות מסיבית 0 עד סיבית 8), והשאר הוא אפס (אפסים), כלומר מסיבית 9 עד סיבית 31 יש אפסים.

כלומר המספר נשמר בזיכרון בצורה הבאה:

00000000000000000000000100001110

ומכאן שעדיף לנו לטפל בטיפוס הנתונים byte אם רצינו לטפל בסיביות של מספרים. אבל גם אם נטפל במשתנים מטיפוס int, נטפל בסיביות הראשונות LSB, ושאר הסיביות שייצאו מחוץ לתחום המשלים ל-2 יהיה ערכן לא נכון, וזאת מפני שב-int אנו מטפלים במספרים בעלי סימן.

כמובן, מספר זה (270) אי אפשר לשמור בטיפוס הנתונים byte, מפני שהוא גדול מ-255, וכפי שראינו הוא דורש 9 סיביות כדי להישמר (מסיבית 0 עד סיבית 8).

דוגמה 10.3
byte num = 305;לא ניתן, כי byte אינו יכול להכילמספרים גדולים מ-255
דוגמה 10.4
byte num = 200; ➔ 11001000
11001000

10.2 הצבת מספרים בבסיסים שונים במשתנים מתוך התוכנית

בשפת סי שארפ אנו יכולים להציב מספרים במשתנים בתוך התוכנית בעזרת הפעולה =

(1) הצבת מספר עשרוני (Dec):

אם רצינו להציב מספר עשרוני במשתנה, כותבים אותו ישירות. כמו:

num = 44; // num = (44)10 = (2C)HEX = (00101100)2

(2) הצבה בבסיס 16 (HEX):

אם רצינו להציב מספר בבסיס 16 (HEX) במשתנה, כותבים אותו כך שלפניו נכתוב 0x או 0X (אפס והאות x קטנה או גדולה). כמו:

num =0x44; // num = (68)10 = (44)HEX = (01000100)2

(3) הצבה בבסיס הבינארי (Bin):

אם רצינו להציב מספר בבסיס הבינארי (Bin) במשתנה, כותבים אותו כך שלפניו נכתוב 0b או 0B (אפס והאות b קטנה או גדולה). כמו:

num =0b10100111; // num = (167)10 = (A7)HEX = (10100111)2

המשתנה num יכול להיות מטיפוס int או byte.

10.3 הדפסת ערכי משתנים בבסיסים שונים על המסך

אנו יכולים לשמור ערכים שונים בתוך המשתנים, לפי הטיפוס שלהם.

אם רצינו להדפיס ערך של משתנה על המסך בבסיס עשרוני (המצב הרגיל), נשתמש בפקודה Console.Write ובכלי {} כך:

{0} או {0:d} או {0:D} בתוך המחרוזת בפקודה Console.Write

אם רצינו להדפיס ערך של משתנה על המסך בבסיס 16 (HEX), נשתמש בפקודה Console.Write ובכלי {} כך:

{0:x} או {0:X} בתוך המחרוזת בפקודה Console.Write

10.4 הפעולות על הנתונים

למדנו קודם את כל הפעולות הבאות:

הפעולההסבר
+חיבור
-חיסור
*כפל
/חילוק
%שארית החילוק
++קידום ב-1
--הפחתה ב-1
+=חיבור המספר עם הערך הקודם
-=חיסור המספר מן הערך הקודם
*=כפל המספר בערך הקודם
/=חילוק הערך הקודם במספר
%=שארית חילוק הערך הקודם במספר
המחלקה Mathחישובים מתמטיים מיוחדים
||יחס "או" לוגי בתנאים
&&יחס "וגם" לוגי בתנאים
==השוואה (שוויון)
!=השוואה (לא שווה)
<השוואה (אי-שוויון)
>השוואה (אי-שוויון)
<=השוואה (אי-שוויון או שוויון)
>=השוואה (אי-שוויון או שוויון)

כל הפעולות האלה פעלו על הנתונים השונים בבסיס העשרוני.

נלמד פעולות חדשות על סיביות המספר השמורות (סיביותיו, שמכילות מספר בבסיס הבינארי 0 או 1):

הפעולהמה היא עושההסבר
&bitwise Andפעולת "וגם" And על כל סיבית וסיבית מסיביות המספר השמורות בבסיס הבינארי
|bitwise Orפעולת "או" Or על כל סיבית וסיבית מסיביות המספר השמורות בבסיס הבינארי
~bitwise Notפעולת שלילה Not על כל סיבית וסיבית מסיביות המספר השמורות בבסיס הבינארי
^bitwise XORפעולת XOR על כל סיבית וסיבית מסיביות המספר השמורות בבסיס הבינארי
<<Shift Leftהזזת סיביות המספר השמורות בסיבית אחת שמאלה
>>Shift Rightהזזת סיביות המספר השמורות בסיבית אחת ימינה
aba | b
000
011
101
111
aba&b
000
010
100
111
a~a
01
10
aba^b
000
011
101
110

הערות:

הזזת סיבית שמאלה:

aa7a6a5a4a3a2a1a0a<<1a6a5a4a3a2a1a00a7

הזזת סיבית ימינה:

bb7b6b5b4b3b2b1b0b>>10b7b6b5b4b3b2b1b0
0001 ←➔ 0010 ←➔ 0100 ←➔ 1000
דוגמה 10.5
static void Main(string[] args)
{
 int a = 7; // 7 = 00000111
 int b = 2; // 2 = 00000010
 int not_a , not_b,c,d,e;
 not_a = ~a; //not_a=11111000 =>it`s negative so with 2`C it`s negative of 8
 not_b = ~b; //not_b=11111101 =>it`s negative so with 2`C it`s negative of 3
 c = a | b;
 d = a & b;
 e = a ^ b;

 Console.WriteLine("Value of not_a is {0}", not_a);
 Console.WriteLine("Value of not_b is {0}", not_b);
 Console.WriteLine("Value of a|b is {0}", c);
 Console.WriteLine("Value of a&b is {0}", d);
 Console.WriteLine("Value of a^b is {0}", e);
 Console.ReadKey();
}

תוצאת הרצת התוכנית:

C:\Users\Hammam\source\repos\Co
Value of not_a is -8
Value of not_b is -3
Value of a|b is 7
Value of a&b is 2
Value of a^b is 5

הסבר:

a00000111~a11111000b00000010~b11111101

אחרי ביצוע פעולת Not סיבית-סיבית, כאן אנו רואים שהמספרים שמתקבלים הם שליליים (מפני שסיבית הסימן היא 1 (פעילה)), ולכן כדי לדעת מהם המספרים השליליים האלה, נעשה להם משלים ל-2 (2`C), ויופיע לנו הערך החיובי הנגדי של המספרים השליליים האלה, וכך נדע מהם.

a00000111b00000010a|b00000111= 7a&b00000010=2a^b00000101=5

דוגמאות לפעולות הזזת סיביות שמאלה (<<) והזזה ימינה (>>):

static void Main(string[] args)
{
    int a = 11; // 11 = 00001011
    int b = 60;  // 60 = 00111100
    int c,d;
    c = a << 2; // 2 steps left
    d = b >> 2; // 2 steps right

    Console.WriteLine("c is {0}", c);
    Console.WriteLine("d is {0}", d);
}

תוצאת הרצת התוכנית היא:

C:\Users\Hammam\
c is 44
d is 15
a00001011=11a<<200101100=44יציאה מןהתחום00כניסת אפסים
b00111100= 60b>>200001111= 15יציאה מןהתחום00כניסת אפסים

10.5 שימוש במיסוך (mask)

מטרת הפעולה הזאת (הטכניקה) היא לקרוא ערך של סיבית מסוימת מתוך מילה. למשל, אנו רוצים לבדוק מהו ערך הסיבית השישית במספר 241 (שהוא 11110001).

פעולת המיסוך (הצבת מסכה) היא פעולה שבה אנו משתמשים בפעולת And עם מסכה, שיש בה סיביות אפס במקומות שאיננו מתעניינים בהם (בסיביות שאינן חשובות לנו), ואילו ערך הסיבית שחשובה לנו במסכה הוא 1.

בדוגמה המסכה היא (00100000): כל הסיביות 0 (מן הראשונה עד החמישית, והשביעית והשמינית), ואילו בסיבית השישית, שמעניינת אותנו במספר המקורי (241), אנו מציבים במסכה 1.

הדבר מבטיח לנו שכל סיביות המספר המקורי יתבטלו (יהפכו לאפס, מפני שפעולת "וגם" עם אפס תיתן בהכרח אפס), ואילו הסיבית הרצויה תישאר (מפני שפעולת "וגם" עם הסיבית הרצויה משאירה את ערך הסיבית הרצויה כפי שהוא: אם היא אפס תישאר אפס, ואם היא 1 תישאר 1)

אחר כך, אחרי פעולת "וגם" עם המסכה, נשארת לנו סיבית אחת בנתון, אבל:

סיבית 8סיבית 7סיבית 6סיבית 5סיבית 4סיבית 3סיבית 2סיבית 1aa7a6a5a4a3a2a1a0&&&&&&&&מסכה00100000a&מסכה00a500000"0""1"00000000=000100000=1
דוגמה 10.6
static void Main(string[] args)
{
  int num = 117;  // 117 = 01110101
  int mask = 0b00010000;  // mask = 16;
  int res;

  res = num & mask;
  if(res==0)
      Console.WriteLine("Bit number 5 in number {0} is 0",num);
  else
      Console.WriteLine("Bit number 5 in number {0} is 1", num);
}

תוצאת הרצת התוכנית:

C:\Users\Hammam\source\repos\ConsoleApp38\
Bit number 5 in number 117 is 1

בדיקה אם המספר שאנו קולטים זוגי או לא, בלי להשתמש במודולו:

ידוע שמספר הוא זוגי אם הסיבית הנמוכה ביותר שלו LSB בבסיס הבינארי היא 0, ואילו אם הסיבית הנמוכה ביותר שלו LSB היא 1, המספר אי-זוגי. לכן סיבית זו חשובה לנו.

אם נבצע מסכה שיש בה 1 רק בסיבית הימנית LSB, כלומר 00000001, נקבל או אפס או 1 אחרי פעולת המיסוך (And), ומי שיכריע בכך היא הסיבית הראשונה במספר המקורי, שמעניינת אותנו (LSB).

אם התוצאה היא:

שאלה 10.1: כתוב תוכנית שקולטת מן המשתמש מספר שלם ומדפיסה על המסך אם מספר זה זוגי (even) או אי-זוגי (odd), בלי להשתמש בפעולה %

פתרון:

static void Main(string[] args)
{
   int num;
   int mask = 0b00000001;  // mask = 1;
   int res;

   Console.Write("Insert a number: ");
   num = int.Parse(Console.ReadLine());
   res = num & mask;
   if(res==0)
       Console.WriteLine("The number {0} is even",num);
   else
       Console.WriteLine("The number {0} is odd", num);
}

תוצאות הרצת התוכנית:

C:\Users\Hammam\source
Insert a number: 64
The number 64 is even
C:\Users\Hammam\source\repos\Consol
Insert a number: 37
The number 37 is odd
המאם ותד (أ. همام وتد) — כל זכויות הספר שמורות למחבר. הספר נכתב בערבית, ותרגם אותו לעברית פהד גאנם. המהדורה העברית מתפרסמת באישור המחבר, עם תיקונים שאישר. ליצירת קשר עם המחבר: hammam4112@gmail.com