JavaRush /وبلاگ جاوا /Random-FA /عملیات بیتی در جاوا

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

در گروه منتشر شد
احتمالاً با کلمه ضرب و شتم آشنا هستید. اگر نه، بیایید با آن آشنا شویم :) بیت حداقل واحد اندازه گیری اطلاعات در یک کامپیوتر است. نام آن از انگلیسی " رقم باینری " - "عدد باینری" گرفته شده است. یک بیت را می توان به عنوان یکی از دو عدد بیان کرد: 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 در باینری است. ما در واقع این عدد را به بیت های جداگانه - صفر و یک تقسیم کرده ایم. با آنهاست که می توانیم عملیاتی به نام bitwise را انجام دهیم.
  • ~- عملگر "NOT" به صورت بیتی.

خیلی ساده کار می کند: از هر بیت از عدد ما عبور می کند و مقدار آن را به عکس تغییر می دهد: صفر به یک، یک به صفر. اگر آن را روی عدد 342 خود اعمال کنیم، این چیزی است که به دست می‌آید: 101010110 - عدد 342 در باینری 010101001 - نتیجه عبارت ~342 اما از آنجایی که یک متغیر int 4 بایت می‌گیرد، یعنی. 32 بیت، در واقع، عدد در متغیر به صورت زیر ذخیره می شود: 00000000 00000000 00000001 01010110- عدد 342 در متغیری از نوع int در جاوا 11111111 11111111 11111110 10101001- نتیجه عبارت ~342 در جاوا. بیایید سعی کنیم در عمل این کار را انجام دهیم:
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 خواهد بود & . &از دو عدد با یکدیگر، سپس بیت دوم، سوم و غیره. همانطور که می بینید، فقط در دو مورد هر دو بیت در اعداد برابر با 1 بودند (بیت اول و پنجم). نتیجه همه مقایسه‌های دیگر 0 بود. بنابراین در نهایت عدد 100010000 را به دست آوردیم. در سیستم اعشاری با عدد 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
همه چیز را درست شمردیم! :)
  • ^- 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
فوق العاده! همه چیز دقیقاً همانطور است که فکر می کردیم :) اکنون زمان آن است که با عملیاتی به نام bit shift آشنا شویم. نام، در اصل، برای خود صحبت می کند. تعدادی عدد می گیریم و بیت هایش را به چپ و راست می بریم :) ببینیم چه شکلی است:

شیفت به چپ

تغییر سمت چپ بیت ها با علامت << مثال نشان داده می شود:
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 استفاده می کنیم. Int32 بیت از حافظه کامپیوتر را اشغال می کند. شماره 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 بیتی داریم که فقط از صفر تشکیل شده است. طبیعتاً در سیستم اعشاری با 0 مطابقت دارد. یک قانون ساده برای به خاطر سپردن جابه‌جایی‌های چپ: با هر جابجایی به چپ، عدد در 2 ضرب می‌شود. برای مثال، بیایید سعی عملیات بیتی - 4کنیم نتیجه عبارت را بدون عکس با بیت محاسبه کنیم. 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

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

هنگام نوشتن یا خواندن کد، اغلب با عباراتی روبرو می شوید که در آن چندین عملیات به طور همزمان انجام می شود. بسیار مهم است که بدانیم آنها به چه ترتیبی اجرا خواهند شد، در غیر این صورت نتیجه ممکن است غیر منتظره باشد. از آنجایی که عملیات های زیادی در جاوا وجود دارد، همه آنها به یک جدول ویژه تقسیم شدند:

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

اپراتورها تقدم
پسوند 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 = 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) و در انتها نتیجه به falseمتغیر اختصاص می یابد x. تخصیص به طور کلی کمترین اولویت را در بین تمام عملیات دارد - به جدول نگاه کنید.

اوه! سخنرانی ما طولانی بود، اما شما آن را انجام دادید! اگر برخی از بخش‌های این سخنرانی و سخنرانی‌های قبلی را به طور کامل متوجه نشدید، نگران نباشید، در آینده بیش از یک بار به این موضوعات خواهیم پرداخت. در اینجا چند لینک مفید برای شما آورده شده است:
  • عملگرهای منطقی - سخنرانی JavaRush در مورد عملیات منطقی. ما به این زودی به آنها نخواهیم رسید، اما اکنون می توانید آنها را بخوانید، هیچ آسیبی نخواهید داشت
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION