CodeGym /وبلاگ جاوا /Random-FA /عملگرهای جاوا Bitwise
John Squirrels
مرحله
San Francisco

عملگرهای جاوا Bitwise

در گروه منتشر شد
در درس امروز با عملگرهای Java Bitwise آشنا می شویم و نمونه هایی از نحوه کار با آنها را در نظر می گیریم. احتمالاً با کلمه «بیت» آشنا هستید. اگر نه، بیایید معنی آن را به خاطر بیاوریم :) بیت کوچکترین واحد اطلاعات در یک کامپیوتر است. نام آن از رقم باینری گرفته شده است . یک بیت را می توان با یکی از دو عدد بیان کرد: 1 یا 0. یک سیستم اعداد باینری خاص بر اساس یک ها و صفرها وجود دارد. ما اینجا به جنگل ریاضی نخواهیم پرداخت. ما فقط توجه می کنیم که هر عددی در جاوا می تواند به فرم باینری تبدیل شود. برای این کار باید از کلاس های wrapper استفاده کنید.
عملگرهای بیتی - 1
به عنوان مثال، در اینجا نحوه انجام این کار برای int آمده است :
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
خروجی کنسول: 101010110 1010 10110 (فضا را برای خواندن راحت تر اضافه کردم) عدد 342 در سیستم اعشاری است. ما در واقع این عدد را به بیت های جداگانه تقسیم کرده ایم: صفر و یک. عملیاتی که روی بیت ها انجام می شود، بیتی نامیده می شود .
  • ~ - به صورت بیتی نه.
این عملگر بسیار ساده است: از روی هر بیت از عدد ما عبور می کند و بیت را ورق می زند: صفرها یک می شوند و یک ها صفر می شوند. اگر آن را روی عدد 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
همانطور که می بینید، کاملاً شبیه به AND منطقی ( && ) است . به یاد می آورید که عملگر && فقط در صورتی true برمی گرداند که هر دو عملوند درست باشند . Bitwise & به روشی مشابه کار می کند: دو عدد را بیت به بیت مقایسه می کند. مقایسه عدد سومی را تولید می کند. برای مثال، بیایید اعداد 277 و 432 را در نظر بگیریم: 110110000 برابر با 277 است که به عنوان یک عدد باینری نشان داده می شود . از آنجا که این یک عملگر AND است، نتیجه 1 خواهد بود فقط در صورتی که هر دو بیت 1 باشند. در هر صورت، نتیجه 0 است . اعداد، سپس بیت دوم، سپس سوم، و غیره. همانطور که می بینید، تنها در دو مورد هر دو بیت متناظر در اعداد برابر با 1 هستند (بیت اول و پنجم). همه مقایسه های دیگر 0 ها را تولید کردند. بنابراین در نهایت عدد 10001000 را به دست آوردیم. در سیستم اعشاری با عدد 272 مطابقت دارد. بیایید بررسی کنیم:
public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
خروجی کنسول: 272
  • | - بیتی OR.
این عملگر به همین صورت عمل می کند: مقایسه دو عدد بیت به بیت. فقط حالا اگر حداقل یکی از بیت ها 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 معمولی true را برمی گرداند. اما لازم نیست یکی باشد: اگر هر دو عملوند درست باشد، نتیجه درست است. اما OR انحصاری فقط در صورتی true را برمی گرداند که دقیقا یکی از عملوندها درست باشد. اگر هر دو عملوند true باشند، OR معمولی true را برمی گرداند ("حداقل یک true")، اما XOR false را برمی گرداند. به همین دلیل به آن 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 Super! همه چیز همان طور است که فکر می کردیم :) حالا وقت آن است که با عملگرهای bit shifts آشنا شویم. نام برای خودش صحبت می کند. تعدادی عدد را می گیریم و بیت های آن را به چپ یا راست حرکت می دهیم :) بیایید ببینیم چگونه به نظر می رسد:

جابجایی به چپ

جابجایی بیت ها به چپ با << در اینجا یک مثال نشان داده شده است:
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 استفاده می کنیم. اینت ها 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

اولویت عملگر در جاوا

هنگام نوشتن و خواندن کد، اغلب عباراتی را خواهید یافت که چندین عملیات را با هم ترکیب می کنند. درک ترتیب اجرای آنها بسیار مهم است (در غیر این صورت، ممکن است از نتیجه شگفت زده شوید) از آنجا که جاوا عملیات زیادی دارد، به هر یک از آنها مکانی در یک جدول خاص اختصاص داده شده است:

اولویت اپراتور

اپراتورها تقدم
پسوند expr++ expr--
یگانه ++expr --expr +expr ~ !
ضربی * / %
افزودنی + -
تغییر مکان << >> >>>
رابطه ای < > <= >= نمونه
برابری == !=
به صورت بیتی و &
بیتی انحصاری OR ^
بیتی شامل 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;
برای مثال، عملگر add( + ) دارای اولویت بالاتری نسبت به عملگر مقایسه != (نه برابر) است. بنابراین در بیان
boolean x = 7 != 6+1;
ابتدا عملیات 1+6 انجام می شود، سپس بررسی 7 != 7 (که به صورت نادرست ارزیابی می شود) و در نهایت تخصیص نتیجه (نادرست) به متغیر x (تخصیص عموماً کمترین اولویت را در بین همه عملگرها دارد؛ ببینید). میز). اوه! این یک درس بزرگ بود، اما شما آن را انجام دادید! اگر برخی از این یا درس های قبلی را به طور کامل متوجه نشدید، نگران نباشید. در آینده بیش از یک بار به این موضوعات خواهیم پرداخت. چند درس CodeGym در مورد عملیات منطقی و عددی. ما به این زودی ها به این موارد نخواهیم رسید، اما ضرری ندارد که اکنون آنها را بخوانید.
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION