CodeGym /مدونة جافا /Random-AR /مشغلي جافا Bitwise
John Squirrels
مستوى
San Francisco

مشغلي جافا Bitwise

نشرت في المجموعة
في درس اليوم، سوف نتعرف على مشغلي Java Bitwise ونأخذ في الاعتبار أمثلة حول كيفية العمل معهم. ربما تكون على دراية بكلمة "بت". إذا لم يكن الأمر كذلك، فلنتذكر ما يعنيه :) البت هو أصغر وحدة معلومات في الكمبيوتر. اسمها يأتي من الرقم الثنائي . يمكن التعبير عن البتة بأحد الرقمين: 1 أو 0. يوجد نظام أرقام ثنائي خاص يعتمد على الآحاد والأصفار. لن نخوض في غابة رياضية هنا. سنلاحظ فقط أن أي رقم في Java يمكن تحويله إلى شكل ثنائي. للقيام بذلك، تحتاج إلى استخدام فئات المجمع.
عوامل تشغيل البت - 1
على سبيل المثال، إليك كيفية القيام بذلك لـ int :
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
إخراج وحدة التحكم: 101010110 1010 10110 (أضفت مسافة لتسهيل القراءة) هو الرقم 342 في النظام العشري. لقد قمنا بالفعل بتقسيم هذا الرقم إلى أجزاء فردية: أصفار وآحاد. تسمى العمليات التي يتم إجراؤها على البتات bitwise .
  • ~ - لا بالبت.
هذا العامل بسيط للغاية: فهو يمرر فوق كل جزء من رقمنا، ويقلب البت: تصبح الأصفار واحدًا، والآحاد تصبح أصفارًا. إذا طبقناها على الرقم 342، فإليك ما يحدث: 101010110 هو 342 ممثلًا كرقم ثنائي 010101001 هي قيمة التعبير ~342 دعنا نحاول وضع ذلك موضع التنفيذ:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(~x);
   }
}
مخرجات وحدة التحكم: 169 169 هي نتيجتنا ( 010101001 ) في النظام العشري المألوف :)
  • & - بالبت و
كما ترون، يبدو مشابهًا تمامًا للرمز المنطقي AND ( && ). كما تتذكر، فإن عامل التشغيل && لا يُرجع صحيحًا إلا إذا كان كلا المعاملين صحيحين . يعمل Bitwise بطريقة مماثلة: فهو يقارن رقمين شيئًا فشيئًا. المقارنة تنتج رقما ثالثا. على سبيل المثال، لنأخذ الرقمين 277 و432: 110110000 هو 277 ممثلًا كرقم ثنائي 1000101011 هو 432 ممثلًا كرقم ثنائي. بعد ذلك، يقوم عامل التشغيل بمقارنة البت الأول من الرقم العلوي بالبت الأول من الرقم السفلي. نظرًا لأن هذا عامل تشغيل AND، فستكون النتيجة 1 فقط إذا كان كلا البتين 1. وفي أي حالة أخرى، تكون النتيجة 0. 100010101 & 110110000 _______________ 10001000 - نتيجة العامل & أولاً، نقارن البتات الأولى من الاثنين الأرقام، ثم البت الثاني، ثم الثالث، وهكذا. كما ترون، في حالتين فقط تكون البتات المقابلة في الأرقام تساوي 1 (البتتين الأولى والخامسة). أنتجت جميع المقارنات الأخرى 0s. وفي النهاية حصلنا على الرقم 10001000. وهو يتوافق في النظام العشري مع الرقم 272. دعونا نتحقق:
public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
مخرج وحدة التحكم: 272
  • | - bitwise أو.
يعمل هذا العامل بنفس الطريقة: مقارنة رقمين شيئًا فشيئًا. الآن فقط، إذا كان أحد البتات على الأقل هو 1، فستكون النتيجة 1. فلننظر إلى نفس الأرقام (277 و432): 100010101 | 110110000 _______________ 110110101 - نتيجة | المشغل هنا حصلنا على نتيجة مختلفة: البتات الوحيدة التي تظل أصفارًا هي تلك البتات التي كانت أصفارًا في كلا الرقمين. والنتيجة هي الرقم 110110101. في النظام العشري، يتوافق مع الرقم 437 دعونا نتحقق:
public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
إخراج وحدة التحكم: 437 لقد حسبنا كل شيء بشكل صحيح! :)
  • ^ - XOR للبت (OR حصريًا)
لم نواجه هذا المشغل بعد. ولكن لا يوجد شيء معقد في هذا الأمر. إنه مشابه لمشغل OR العادي. هناك اختلاف واحد: يُرجع العامل العادي OR صحيحًا إذا كان مُعامل واحد على الأقل صحيحًا. ولكن ليس من الضروري أن يكون واحدًا: إذا كان كلا المعاملين صحيحًا، فإن النتيجة صحيحة. لكن الحصري OR يُرجع صحيحًا فقط إذا كان أحد المعاملات صحيحًا. إذا كان كلا المعاملين صحيحين، فإن العامل العادي OR يُرجع صحيحًا ("صحيح واحد على الأقل")، لكن XOR يُرجع خطأ. ولهذا السبب يطلق عليه اسم OR الحصري. بمعرفة كيفية عمل معاملات البت السابقة، ربما يمكنك بسهولة حساب 277 ^ 432. لكن دعنا نتعمق فيها معًا مرة أخرى :) 100010101 ^ 110110000 _______________ 010100101 - نتيجة عامل التشغيل ^ هذه هي النتيجة التي حصلنا عليها. تلك البتات التي كانت متماثلة في كلا الرقمين تنتج 0 (مما يعني فشل الاختبار "الوحيد"). لكن البتات التي شكلت زوجًا من 0-1 أو 1-0 أصبحت وحدات. النتيجة لدينا هي الرقم 010100101. في النظام العشري، يتوافق مع الرقم 165. دعونا نرى ما إذا كانت حساباتنا صحيحة:
public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
إخراج وحدة التحكم: 165 سوبر! كل شيء كما كنا نظن :) الآن حان الوقت للتعرف على مشغلي التحولات البتية. الاسم يتحدث عن نفسه. نأخذ رقمًا ما، ونحرك أجزاءه إلى اليسار أو اليمين :) دعونا نرى كيف يبدو:

تحول اليسار

تتم الإشارة إلى تحول البتات إلى اليسار بواسطة << وإليك مثال:
public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
في هذا المثال، الرقم x = 64 يسمى القيمة. إنها أجزاء القيمة التي سنقوم بتغييرها. سنقوم بنقل البتات إلى اليسار (كان بإمكانك تخمين ذلك من خلال اتجاه العامل << ) في النظام الثنائي، الرقم 64 = 1000000 الرقم y = 3 يسمى مسافة الإزاحة. تشير مسافة الإزاحة إلى عدد البتات إلى اليمين/اليسار التي تريد إزاحتها بتات الرقم x. في مثالنا، سنقوم بإزاحتها بمقدار 3 بتات إلى اليسار. لرؤية عملية التحول بشكل أكثر وضوحا، انظر إلى الصورة. في هذا المثال، نستخدم int s. تشغل Ints 32 بت في ذاكرة الكمبيوتر. هكذا يبدو الرقم الأصلي 64:
مشغلي البت - 2
والآن نأخذ كل جزء من البتات لدينا وننقلها حرفيًا إلى اليسار بمقدار 3 أماكن:
مشغلي البت - 3
نلقي نظرة على ما حصلنا عليه. كما ترون، لقد تغيرت جميع البتات لدينا، وتمت إضافة 3 أصفار أخرى من حافة النطاق. ثلاثة، لأننا أزحنا بمقدار 3. وإذا أزحنا بمقدار 10، فسيتم إضافة 10 أصفار. وبالتالي، فإن التعبير x << y يعني "إزاحة بتات الرقم x إلى اليسار بمقدار y". نتيجة التعبير لدينا هي الرقم 1000000000، وهو 512 في النظام العشري. دعونا تحقق:
public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
مخرج وحدة التحكم: 512 بقعة على! من الناحية النظرية، يمكن إزاحة البتات إلى ما لا نهاية، ولكن نظرًا لأن رقمنا هو int ، فلدينا 32 رقمًا ثنائيًا فقط متاحًا. من هذه، 7 مشغولة بالفعل بـ 64 (1000000). ولذلك، إذا قمنا بإزاحة 27 مكانًا إلى اليسار، فإن المكان الوحيد لدينا سوف يتجاوز نطاق نوع البيانات ويضيع. ولن يبقى سوى الأصفار!
public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 26;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
مخرجات وحدة التحكم: 0 كما هو متوقع، تجاوزت الـ 32 بت المتاحة واختفت. لقد انتهينا برقم 32 بت يتكون من أصفار فقط.
مشغلي البت - 4
وبطبيعة الحال، هذا يتوافق مع 0 في النظام العشري. إليك قاعدة بسيطة لتذكر التحولات إلى اليسار: لكل تحول إلى اليسار، يتم ضرب الرقم في 2. دعونا نحاول حساب التعبير التالي بدون صور البتات 111111111 << 3 نحتاج إلى ضرب الرقم 111111111 في 2 . ونتيجة لذلك، حصلنا على 888888888. دعونا نكتب بعض التعليمات البرمجية ونتحقق:
public class Main {

   public static void main(String[] args) {
       System.out.println(111111111 << 3);
   }
}
إخراج وحدة التحكم: 888888888

التحول إلى اليمين

يُشار إلى هذه العملية بـ >> . إنه يفعل نفس الشيء، ولكن في الاتجاه الآخر! :) لن نعيد اختراع العجلة. دعونا نحاول مع نفس int 64.
public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 2;// Shift distance

       int z = (x >> y);
       System.out.println(z);
   }
}
مشغلي البت - 5
عوامل تشغيل البت - 6
ونتيجة للتحول إلى اليمين بمقدار 2، فإن الصفرين الأقصىين في عددنا يتحركان خارج النطاق ويتم فقدانهما. نحصل على 10000، وهو ما يتوافق مع الرقم 16 في النظام العشري. مخرجات وحدة التحكم: 16 إليك قاعدة بسيطة لتذكر التحولات إلى اليمين: كل تحول إلى اليمين يقسم على اثنين، مع تجاهل أي باقي. على سبيل المثال، 35 >> 2 يعني أننا بحاجة إلى قسمة 35 على 2 مرتين، مع تجاهل الباقي 35/2 = 17 (تجاهل الباقي 1) 17/2 = 8 (تجاهل الباقي 1) في النهاية، 35 >> 2 يجب أن يكون تكون مساوية لـ 8. دعونا نتحقق:
public class Main {

   public static void main(String[] args) {
       System.out.println(35 >> 2);
   }
}
مخرج وحدة التحكم: 8

أسبقية عامل التشغيل في Java

أثناء كتابة التعليمات البرمجية وقراءتها، ستجد غالبًا تعبيرات تجمع بين عدة عمليات. من المهم جدًا فهم الترتيب الذي سيتم تنفيذه به (وإلا فقد تتفاجأ بالنتيجة). نظرًا لأن Java بها الكثير من العمليات، فقد تم تخصيص مكان لكل منها في جدول خاص:

أسبقية المشغل

العاملين الأولوية
postfix إكسبر++ إكسبر--
أحادي ++expr --expr +expr ~ !
مضاعف * / %
المضافة + -
يحول << >> >>>
العلائقية < > <= >= مثيل
المساواة == !=
بالبت و &
حصريًا للبت OR ^
شاملاً للبت OR |
منطقي و &&
منطقي أو ||
ثلاثي ؟ :
تكليف = += -= *= /= %= &= ^= |= <<= >>= >>>=
يتم تنفيذ كافة العمليات من اليسار إلى اليمين، مع مراعاة أسبقيتها. على سبيل المثال، إذا كتبنا
int x  = 6 - 4/2;
ثم يتم إجراء عملية القسمة ( 4/2 ) أولاً. وعلى الرغم من أنها تأتي في المرتبة الثانية، إلا أن لها أسبقية أعلى. تشير الأقواس والأقواس إلى الحد الأقصى للأسبقية. ربما تتذكر ذلك من المدرسة. على سبيل المثال، إذا قمت بإضافتها إلى التعبير
int x  = (6 - 4)/2;
ثم يتم إجراء الطرح أولا، لأنه محاط بين قوسين. أسبقية عامل التشغيل المنطقي && منخفضة نوعًا ما (انظر الجدول)، لذا عادةً ما تكون الأخيرة. على سبيل المثال:
boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
سيتم تنفيذ هذا التعبير على النحو التالي:
  • 4/2 = 2
boolean x = 6 - 2 > 3 && 12*12 <= 119;
  • 12*12 = 144
boolean x = 6 - 2 > 3 && 144 <= 119;
  • 6-2 = 4
boolean x = 4 > 3 && 144 <= 119;
بعد ذلك، يتم تنفيذ عوامل المقارنة:
  • 4 > 3 = صحيح
boolean x = true && 144 <= 119;
  • 144 <= 119 = خطأ
boolean x = true && false;
وأخيرًا، سيتم تنفيذ عامل التشغيل AND ( && ) أخيرًا.
boolean x = true && false;
boolean x = false;
على سبيل المثال، عامل الإضافة ( + ) له أسبقية أعلى من عامل المقارنة != (غير متساوي)؛ ولذلك في التعبير
boolean x = 7 != 6+1;
سيتم تنفيذ العملية 6+1 أولاً، ثم التحقق من 7 != 7 (الذي يتم تقييمه على أنه خطأ)، وأخيرًا تعيين النتيجة (خطأ) إلى المتغير x (يكون التعيين عمومًا له الأسبقية الأقل بين جميع العوامل؛ راجع الطاولة). أوف! لقد كان درسًا كبيرًا، لكنك فعلته! إذا لم تفهم تمامًا بعضًا من هذه الدروس أو الدروس السابقة، فلا تقلق. وسنتطرق لهذه المواضيع أكثر من مرة في المستقبل. بعض دروس CodeGym حول العمليات المنطقية والعددية. لن نصل إلى هذه في أي وقت قريب، ولكن لا ضرر من قراءتها الآن.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION