JavaRush /مدونة جافا /Random-AR /عمليات Bitwise في Java

عمليات Bitwise في Java

نشرت في المجموعة
ربما تكون على دراية بكلمة "تغلب". إذا لم يكن الأمر كذلك، فلنتعرف عليها :) البت هو الحد الأدنى لوحدة قياس المعلومات في الكمبيوتر. يأتي اسمها من " الرقم الثنائي " الإنجليزي - "الرقم الثنائي". يمكن التعبير عن البت كواحد من رقمين: 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.
  • ~- عامل التشغيل "NOT" ذو مستوى البت.

إنه يعمل بكل بساطة: فهو يمر عبر كل جزء من رقمنا ويغير قيمته إلى العكس: من الأصفار إلى الآحاد، ومن الآحاد إلى الأصفار. إذا طبقناها على رقمنا 342، فهذا ما نحصل عليه: 101010110 - الرقم 342 في الملف الثنائي 010101001 - نتيجة التعبير ~342 ولكن بما أن المتغير int يأخذ 4 بايت، أي. 32 بت، في الواقع، يتم تخزين الرقم الموجود في المتغير على النحو التالي: 00000000 00000000 00000001 01010110- الرقم 342 في متغير من النوع int في Java 11111111 11111111 11111110 10101001- نتيجة التعبير ~342 في Java دعنا نحاول القيام بذلك عمليًا:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(~x));
   }
}
إخراج وحدة التحكم:
11111111111111111111111010101001
  • &- عامل البت "AND"

كما ترون، فهو مكتوب بشكل مشابه تمامًا لـ "AND" المنطقي ( &&). عامل التشغيل &&، كما تتذكر، لا يعود trueإلا إذا كان كلا المعاملين صحيحين. يعمل Bitwise &بطريقة مماثلة: فهو يقارن رقمين شيئًا فشيئًا. ونتيجة هذه المقارنة هي الرقم الثالث. على سبيل المثال، لنأخذ الرقمين 277 و432: 100010101 - الرقم 277 في النموذج الثنائي 110110000 - الرقم 432 في النموذج الثنائي. بعد ذلك، &يقارن المشغل البت الأول من الرقم العلوي مع البت الأول من الرقم السفلي. وبما أن هذا عامل تشغيل "AND"، فإن النتيجة ستكون مساوية 1 فقط إذا كان كلا البتين يساوي 1. وفي جميع الحالات الأخرى، ستكون النتيجة 0. 100010101 & 110110000 _______________ 100010000 - نتيجة العمل & نقوم أولاً بمقارنة البتات الأولى من رقمين مع بعضهما البعض، ثم البتات الثانية والثالثة، وما إلى ذلك. كما ترون، في حالتين فقط كانت كلتا البتتين بأرقام تساوي 1 (البتين الأول والخامس). وكانت نتيجة جميع المقارنات الأخرى 0. لذلك، في النهاية حصلنا على الرقم 100010000. في النظام العشري، يتوافق مع الرقم 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
لقد أحصينا كل شيء بشكل صحيح! :)
  • ^- حصريًا للبت OR (المعروف أيضًا باسم XOR)
لم نواجه مثل هذا المشغل من قبل. ولكن لا يوجد شيء معقد في هذا الشأن. يبدو وكأنه "أو" عادي. الفرق هو واحد: تُرجع "أو" العادية trueإذا كان مُعامل واحد على الأقل صحيحًا. ولكن ليس بالضرورة واحدا - إذا كان كلاهما موجودا true- فالنتيجة true. لكن "أو" الحصرية لا تُرجع trueإلا إذا كان أحد المعاملات صحيحًا. إذا كان كلا المعاملين صحيحًا، فسيتم إرجاع "أو" العادي true("واحد على الأقل صحيح")، ولكن سيتم إرجاع حصري أو false. ولهذا السبب يطلق عليه حصريا. بمعرفة مبدأ العمليات السابقة، ربما يمكنك بسهولة إجراء العملية 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;//meaning
       int y = 3;//quantity

       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. Intتشغل 32 بت من ذاكرة الكمبيوتر. هذا ما يبدو عليه رقمنا الأصلي 64: عمليات البت - 2والآن، بالمعنى الحرفي للكلمة، نأخذ كل بت لدينا وننقله إلى اليسار بمقدار 3 خلايا: عمليات البت - 3هذا ما حصلنا عليه. كما ترون، لقد تغيرت جميع البتات لدينا، وتمت إضافة 3 أصفار أخرى من خارج النطاق. 3 - لأننا كنا ننتقل بمقدار 3. وإذا كنا ننتقل بمقدار 10، فسيتم إضافة 10 أصفار. لذا فإن التعبير x << yيعني "إزاحة أجزاء عدد хالخلايا y إلى اليسار". وكانت نتيجة التعبير لدينا هي الرقم 1000000000، والذي يساوي في النظام العشري 512. دعونا نتحقق من ذلك:
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 3;//quantity

       int z = (x << y);
       System.out.println(z);
   }
}
إخراج وحدة التحكم:

512
صحيح! من الناحية النظرية، يمكن إزاحة البتات إلى أجل غير مسمى. ولكن بما أن لدينا الرقم int، فلا يوجد سوى 32 خلية متاحة. من بينها 7 مشغولة بالفعل بالرقم 64 (1،000،000). لذلك، إذا قمنا، على سبيل المثال، بإجراء 27 تحولًا إلى اليسار، فإن وحدتنا الوحيدة ستخرج خارج النطاق و"تكتب فوق". ولن يبقى إلا الأصفار!
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 26;//quantity

       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;//meaning
       int y = 2;//quantity

       int z = (x >> y);
       System.out.println(z);
   }
}
عمليات البت - 5عمليات البت - 6ونتيجة للتحول بمقدار 2 إلى اليمين، خرج الصفران الأقصىان لرقمنا خارج النطاق وتم محهما. لقد حصلنا على الرقم 10000، والذي يتوافق في النظام العشري مع الرقم 16. الإخراج إلى وحدة التحكم:

16
قاعدة بسيطة لتذكر التحولات إلى اليمين: كل تحول إلى اليمين يقسم على اثنين، مع تجاهل أي الباقي. على سبيل المثال، 35 >> 2 هذا يعني أننا بحاجة إلى قسمة 35 على 2 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

أسبقية العمليات في جافا

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

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

العاملين الأولوية
postfix expr++ expr--
أحادي ++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 = true

    boolean x = true && 144 <= 119;
  • 144 <= 119 = false

    boolean x = true && false;
  • وأخيرا، سيتم تنفيذ العامل الأخير &&.

    boolean x = true && false;

    boolean x = false;

    عامل الإضافة ( +)، على سبيل المثال، له أسبقية أعلى من عامل المقارنة !=("غير متساوي")؛

    ولذلك في التعبير:

    boolean x = 7 != 6+1;

    أولاً سيتم تنفيذ العملية 6+1، ثم التحقق 7!=7 (خطأ)، وفي النهاية سيتم تعيين النتيجة falseللمتغير x. يتمتع التعيين بشكل عام بأولوية أدنى بين كافة العمليات - انظر إلى الجدول.

أوف! محاضرتنا كانت طويلة لكنك فعلتها! إذا لم تفهم بعض أجزاء هذا الدرس والمحاضرات السابقة بشكل كامل، فلا تقلق، فسوف نتطرق إلى هذه المواضيع أكثر من مرة في المستقبل. فيما يلي بعض الروابط المفيدة لك:
  • العوامل المنطقية - محاضرة JavaRush حول العمليات المنطقية. لن نصل إليها في أي وقت قريب، ولكن يمكنك قراءتها الآن، ولن يكون هناك أي ضرر
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION