( تعداد نمایش : 1811 )

عملگرها ی ریاضی و بیتی

جاوا یک محیط عملگر غنی را فراهم کرده است . اکثر عملگرهای آن را می توان
در چهار گروه طبقه بندی نمود : حسابی arithmetic رفتار بیتی bitwise رابطه ای ralational
و منطقی logical جاوا همچنین برخی عملگرهای اضافی برای اداره
حالتهای خاص و مشخص تعریف کرده است .
نکته : اگر با C++/C آشنایی دارید ، حتما” خوشحال می شوید که بدانید کارکرد
عملگرها در جاوا دقیقا”مشابه با C++/C است . اما همچنان تفاوتهای ظریفی
وجود دارد .

عملگرهای حسابی Arithmetic operators
عملگرهای حسابی در عبارات ریاضی استفاده می شوند و طریقه استفاده از آنها
بهمان روش جبری است . جدول بعدی فهرست عملگرهای حسابی را نشان می دهد :
|
نتیجه آن | عملگر |
|
اضافه نمودن | + | |
تفریق نمودن ( همچنین منهای یکانی ) | – | |
ضرب | * | |
تقسیم | / | |
تعیین باقیمانده | % | |
افزایش | ++ | |
انتساب اضافه نمودن | += | |
انتساب تفرق نمودن | =- | |
انتساب ضرب نمودن | *= | |
انتساب تقسیم نمودن | /= | |
انتساب تعیین باقیمانده | %= | |
کاهش | – - |

عملوندهای مربوط به عملگرهای حسابی باید از نوع عددی باشند . نمی توانید از
این عملگرها روی نوع boolean استفاده کنید ، اما روی انواع char قابل استفاده
هستند ، زیرا نوع char در جاوا بطور ضروری زیر مجموعه ای از int است .

عملگرهای اصلی حسابی
عملیات اصلی حسابی جمع ، تفریق ، ضرب و تقسیم همانطوریکه انتظار دارید
برای انواع عددی رفتار می کنند . عملگر تفرق نمودن همچنین یک شکل یکانی دارد
که عملوند تکی خود را منفی ( یا خنثی ) می کند . بیاد آورید هنگامیکه عملگر
تقسیم به یک نوع عدد صحیح اعمال می شود ، هیچ عنصری کسری یا خرده به جواب ملحق
نمی شود .
برنامه ساده بعدی نشاندهنده عملگرهای حسابی است . این برنامه همچنین تفاوت
بین تقسیم اعشاری و تقسیم عدد صحیح را توضیح می دهد .

+ // Demonstrate the basic arithmetic operators.
+ class BasicMath {
+ public static void main(String args[] ){
+ // arithmetic using integers
+ System.out.println(“Integer Arithmetic”);
+ int a = 1 + 1;
+ int a = a * 3;
+ int a = b / 4;
+ int a = c – a;
+ int a =- d;
+ System.out.println(“a = ” + a);
+ System.out.println(“a = ” + b);
+ System.out.println(“a = ” + c);
+ System.out.println(“a = ” + d);
+ System.out.println(“a = ” + e);
+
+ // arithmetic using doubles
+ System.out.println(“\nFloating Point Arithmetic”);
+ double da = 1 + 1;
+ double db = da * 3;
+ double dc = db / 4;
+ double dd = dc – a;
+ double de =- dd;
+ System.out.println(“da = ” + da);
+ System.out.println(“db = ” + db);
+ System.out.println(“dc = ” + dc);
+ System.out.println(“dd = ” + dd);
+ System.out.println(“de = ” + de);
+ }
+ }

خروجی این برنامه بقرار زیر می باشد :

integer Arithmetic
a=2
b=6
c=1
d=-1
e=1
floating point arithmetic
da=2
db=6
dc=1.5
dd=-0.5
de=0.5

عملگر تعیین باقیمانده The Modulus operator
عملگر تعیین باقیمانده یعنی % ، باقیمانده یک عملیات تقسیم را برمی گرداند.
این عملگر برای انواع عدد اعشاری و انواع عدد صحیح قابل استفاده است . ( اما
در C++/C این عملگر فقط در مورد انواع عدد صحیح کاربرد دارد . ) برنامه بعدی
نشان دهنده عملگر % می باشد :

+ // Demonstrate the % operator.
+ class Modulus {
+ public static void main(String args[] ){
+ int x = 42;
+ double y = 42.3;
+
+ System.out.println(“x mod 10 = ” + x % 10);
+ System.out.println(“y mod 10 = ” + y % 10);
+ }
+ }

هنگامیکه این برنامه را اجرا می کنید ، خروجی زیر حاصل می شود :

x mod 10=2
y mod 10=2.3

عملگرهای انتساب حسابی Arithmetic Assignment operators
جاوا عملگرهای ویژه ای را تدارک دیده که با استفاده از آنها می توان یک
عملیات حسابی را با یک انتساب ترکیب نمود . احتمالا” می دانید که دستوراتی نظیر
مورد زیر در برنامه نویسی کاملا” رایج هستند :

+ a = a + 4;

در جاوا ، می توانید این دستور را بصورت دیگری دوباره نویسی نمایید :

+ a += 4;

این روایت جدید از عملگر انتساب += استفاده می کند هر دو دستورات یک عمل
واحد را انجام می دهند : آنها مقدار aرا ۴ا واحد افزایش می دهند .
اکنون مثال دیگری را مشاهده نمایید :

+ a = a % 2;

که می توان آن را بصورت زیر نوشت :

+ a %= 2;

در این حالت %= باقیمانده a/2 را گرفته و حاصل را مجددا”در aر قرار می دهد.
عملگرهای انتسابی برای کلیه عملگرهای حسابی و دودوئی ( باینری ) وجود دارند .
بنابراین هر دستور با شکل :

Var = var op expression;

عبارت عملگر متغیر متغیر
را می توان بصورت زیر دوباره نویسی نمود :

var op = expression;

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

+ // Demonstrate several assignment operators.
+ class OpEquals {
+ public static void main(String args[] ){
+ int a = 1;
+ int b = 2;
+ int c = 3;
+
+ a += 5;
+ b *= 4;
+ c += a * b;
+ c %= 6;
+ System.out.println(“a = ” + a);
+ System.out.println(“b = ” + b);
+ System.out.println(“c = ” + c);
+ }
+ }

خروجی این برنامه بقرار زیر می باشد :

a=6
b=8
c=3

افزایش و کاهش Increment and Decrement
علامات ++ و — عملگرهای افزایشی و کاهشی جاوا هستند . این عملگرها را قبلا”
معرفی کرده ایم . در اینجا آنها را با دقت بیشتری بررسی می کنیم . همانگونه که
خواهید دید ، این عملگرها خصلتهای ویژه ای دارند که بسیار جالب توجه است . بحث
درباره این عملگرها را از نحوه کار آنها شروع می کنیم .
عملگر افزایشی ، عملوند خود را یک واحد افزایش می دهد . عملگر کاهشی نیز
عملوند خود را یک واحد کاهش می دهد . بعنوان مثال ، دستور زیر را

+ x = x + 1;

می توان با استفاده از عملگر افزایشی بصورت زیر دوباره نویسی نمود :

+ x++;

بطور مشابهی ، دستور زیر را

+ x = x – 1;

می توان بصورت زیر باز نویسی نمود :

+ x–;

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

+ x = 42;
+ y = ++x;

در این حالت ، همانطوریکه انتظار دارید y معادل ۴۳ می شود ، چون افزایش قبل
از اینکه xبه y منتسب شود ، اتفاق می افتد . بدین ترتیب خط y=++ معادل دو
دستور زیر است :

+ x = x + 1;
+ y = x;

اما وقتی که بصورت زیر نوشته می شوند :

+ x = 42;
+ y = x++;

مقدار x قبل از اینکه عملگر افزایشی اجرا شود ، بدست می آید ، بنابراین
مقدار y معادل ۴۲ می شود . البته در هر دو حالت x معادل ۴۳ قرار می گیرد . در
در اینجا ، خط y=x++ معادل دو دستور زیر است :

+ y = x;
+ x = x + 1;

برنامه بعدی نشان دهنده عملگر افزایشی است .

+ // Demonstrate ++.
+ class IncDec {
+ public static void main(String args[] ){
+ int a = 1;
+ int b = 2;
+ int c;
+ int d;
+
+ c = ++b;
+ d = a++;
+ c++;
+ System.out.println(“a = ” + a);
+ System.out.println(“b = ” + b);
+ System.out.println(“c = ” + c);
+ System.out.println(“d = ” + d);
+ }
+ }

خروجی این برنامه بقرار زیر می باشد :

a=2
b=3
c=4
d=1

عملگرهای رفتار بیتی The Bitwise operators
جاوا چندین عملگر رفتار بیتی تعریف نموده که قابل اعمال روی انواع عدد صحیح
شامل long، int،، short،، char،و byteو می باشند . این عملگرها روی بیت های
تکی عملوندهای خود عمل می کنند . این عملگرها را در جدول زیر خلاصه نموده ایم :
نتیجه آن عملگر
Bitwise unary Not
Not یکانی رفتار بیتی ~ Bitwise AND
AND رفتار بیتی & Bitwise OR
OR رفتار بیتی | Bitwise exclusive OR
OR خارج رفتار بیتی ^ shift right
>> حرکت براست shift right zero fill
>>> حرکت براست پر شده با صفر shift left
<< حرکت به چپ Bitwise AND assignment
انتساب AND رفتار بیتی &= Bitwise OR assignment
انتساب OR رفتار بیتی |= Bitwise exclusive OR assignment
انتساب OR خارج رفتار بیتی ^= shift right assignment
انتساب حرکت راست = >>shift right zero fill assignment
انتساب حرکت براست پر شده با صفر = >>>shift left assignment
انتساب حرکت به چپ = <<
از آنجاییکه عملگرهای رفتار بیتی با بیت های داخل یک عدد صحیح سر و کار
دارند ، بسیار مهم است بدانیم که این سر و کار داشتن چه تاثیری ممکن است روی
یک مقدار داشته باشد . بخصوص بسیار سودمند است بدانیم که جاوا چگونه مقادیر
عدد صحیح را ذخیره نموده و چگونه اعداد منفی را معرفی می کند . بنابراین ، قبل
از ادامه بحث ، بهتر است این دو موضوع را باختصار بررسی نماییم .
کلیه انواع صحیح بوسیله ارقام دودوئی ( باینری ) دارای پهنای بیتی گوناگون
معرفی میشوند. بعنوان مثال ، مقدار byte عدد ۴۲ در سیستم باینری معادل ۰۰۱۰۱۰۱۰
است ، که هر یک از این نشانه ها یک توان دو را نشان می دهند که با ۲ به توان ۰
در بیت سمت راست شروع شده است . یا موقعیت بعدی بیت بطرف چپ ۲′یا ۲ا است و به
طرف چپ بیت بعدی ۲ به توان ۲یا ۴ا است ، بعدی ۸ ، ۱۶ ، ۳۲ و همینطور الی آخر
هستند . بنابراین عدد ۴۲ بیت ۱ را در موقعیتهای اول ، سوم و پنجم ( از سمت
راست درنظربگیرید ) دارد. بدین ترتیب ۴۲ معادل جمع ۵ بتوان ۳+۲ بتوان ۱+۲ بتوان ۲
یعنی ۲+۸+۳۲ می باشد .
کلیه انواع عدد صحیح ( باستثنائ char ) اعداد صحیح علامت دار هستند . یعنی
که این انواع مقادیر منفی را همچون مقادیر مثبت می توانند معرفی کنند . جاوا
از یک روش رمزبندی موسوم به مکمل دو (two’s complement) استفاده می کند که در
آن ارقام منفی با تبدیل ( تغییر ۱به ۰ و بالعکس ) کلیه بیت های یک مقدار و
سپس اضافه نمودن ۱ به آن معرفی می شوند . بعنوان مثال برای معرفی ۴۲ ، ابتدا
کلیه بیت های عدد ۴۲ (۰۰۱۰۱۰۱۰) را تبدیل می نماییم که ۱۱۰۱۰۱۰۱ حاصل می شود
آنگاه ۱ را به آن اضافه می کنیم . که حاصل نهایی یعنی ۱۱۰۱۰۱۱۰ معرف عدد ۴۲
خواهد بود . برای رمز گشایی یک عدد منفی ، کافی است ابتدا کلیه بیت های آن را
تبدیل نموده ، آنگاه ۱ را به آن اضافه نماییم . ۴۲- یعنی ۱۱۰۱۰۱۱۰ پس از تبدیل
برابر ۰۰۱۰۱۰۰۱ یا ۴۱ شده و پس از اضافه نمودن ۱ به آن برابر ۴۲ خواهد شد .
دلیل اینکه جاوا( واکثر زبانهای برنامه نویسی )از روش مکمل دو(two’s complement)
استفاده می کنند ، مسئله تقاطع صفرها (Zero crossing) است . فرض کنید یک مقدار byte
برای صفر با ۰۰۰۰۰۰۰۰ معرفی شده باشد. در روش مکمل یک (one’s complement)
تبدیل ساده کلیه بیت ها منجر به ۱۱۱۱۱۱۱۱ شده که صفر منفی را تولید می کند .
اما مشکل این است که صفر منفی در ریاضیات عدد صحیح غیر معتبر است . این مشکل
بااستفاده از روش مکمل دو (two’s complement) برای معرفی مقادیر منفی حل خواهد
شد . هنگام استفاده از روش مکمل دو ، ۱ به مکمل اضافه شده و عدد ۱۰۰۰۰۰۰۰۰
تولید می شود . این روش بیت ۱ را در منتهی الیه سمت چپ مقدار byte قرار داده
تا رفتار مورد نظر انجام گیرد، جایی که ۰با ۰ا یکسان بوده و ۱۱۱۱۱۱۱۱ رمزبندی
شده ۱ است . اگر چه در این مثال از یک مقدار byte استفاده کردیم ، اما همین
اصول برای کلیه انواع عدد صحیح جاوا صدق می کنند .
از آنجاییکه جاوا از روش مکمل دو برای ذخیره سازی ارقام منفی استفاده میکند
و چون کلیه اعداد صحیح در جاوا مقادیر علامت دار هستند بکار بردن عملگرهای
رفتار بیتی براحتی نتایج غیر منتظره ای تولید می کند . بعنوان مثال برگرداندن
بیت بالاتر از حد مجاز (high-order) سبب می شود تا مقدار حاصله بعنوان یک رقم
منفی تفسیر شود ، خواه چنین قصدی داشته باشید یا نداشته باشید . برای جلوگیری
از موارد ناخواسته ، فقط بیاد آورید که بیت بالاتر از حد مجاز (high-order)
علامت یک عدد صحیح را تعیین می کند، صرفنظر از اینکه بیت فوق چگونه مقدار گرفته
باشد .

عملگرهای منطقی رفتار بیتی
عملگرهای منطقی رفتار بیتی شامل &، |،، ^،، ~، هستند. جدول زیر حاصل هر یک
از این عملیات را نشان می دهد . در بحث بعدی بیاد داشته باشید که عملگرهای
رفتار بیتی به بیت های منفرد داخل هر عملوند اعمال می شوند .

A B A|B A&B A^B ~A
0 0 0 0 0 1
1 0 1 0 1 0
0 1 1 0 1 1
1 1 1 1 0 0

NOT

رفتار بیتی
عملگر NOT یکانی یعنی ~ که آن را مکمل رفتار بیتی (bitwise complement) هم
می نامند ، کلیه بیت های عملوند خود را تبدیل می کند . بعنوان مثال ، عدد ۴۲
که مطابق الگوی بیتی زیر است : ۰۰۱۰۱۰۱۰

پس از اعمال عملگر NOT بصورت زیر تبدیل می شود : ۱۱۰۱۰۱۰۱

AND
رفتار بیتی
عملگر AND یعنی & اگر هر دو عملوند ۱ باشند ، یک بیت ۱ تولید می کند . در
کلیه شرایط دیگر یک صفر تولید می شود . مثال زیر را نگاه کنید : ۰۰۱۰۱۰۱۰ ۴۲
& 00001111 15

00001010 10

OR
رفتار بیتی
عملگر OR یعنی | بیت ها را بگونه ای ترکیب می کند که اگر هر یک از بیت های
عملوندها ۱ باشد ، آنگاه بیت حاصله نیز ۱ خواهد بود . به مثال زیر نگاه کنید : ۰۰۱۰۲۰۱۰ ۴۲
| ۰۰۰۰۱۱۱۱ ۱۵

۰۰۱۰۱۱۱۱ ۴۷

XOR
رفتار بیتی
عملگر XOR یعنی ^ بیت ها را بگونه ای ترکیب می کند که اگر دقیقا” یک عملوند ۱
باشد ، حاصل برابر ۱ خواهد شد . در غیر اینصورت ، حاصل ۰ می شود .
مثال بعدی چگونگی کار این عملگر را نشان می دهد . این مثال همچنین یکی از
خصلتهای سودمند عملگر XOR را نمایش می دهد . دقت کنید که هر جا عملوند دوم یک
بیت ۱ داشته باشد ، چگونه الگوی بیتی عدد ۴۲ تبدیل می شود . هر جا که عملوند
دوم بیت ۰ داشته باشد ، عملوند اول بدون تغییر می ماند . هنگام انجام برخی از
انواع عملکردهای بیتی ، این خصلت بسیار سودمند است . ۰۰۱۰۱۰۱۰ ۴۲
^ ۰۰۰۰۱۱۱۱ ۱۵

۰۰۱۰۰۱۰۱ ۳۷

استفاده از عملگرهای منطقی رفتار بیتی
برنامه بعدی نشان دهنده عملگرهای منطقی رفتار بیتی است :

+ // Demonstrate the bitwise logical operators.
+ class BitLogic {
+ public static void main(String args[] ){
+ String binary[] = {
+ “0000″/ “0001″/ “0010″/ “0011″/ “0100″/ “0101″/ “0110″/ “0111″/
+ “1000″/ “1001″/ “1010″/ “1011″/ “1100″/ “1101″/ “1110″/ “1111″
+ };
+ int a = 3; // 0 + 2 + 1 or 0011 in binary
+ int b = 6; // 4 + 2 + 0 or 0110 in binary
+ int c = a | b;
+ int d = a & b;
+ int e = a ^ b;
+ int f =( ~a & b )|( a & ~b);
+ int g = ~a & 0x0f;
+
+ System.out.println(” a = ” + binary[a]);
+ System.out.println(” b = ” + binary[b]);
+ System.out.println(” a|b = ” + binary[c]);
+ System.out.println(” a&b = ” + binary[d]);
+ System.out.println(” a^b = ” + binary[e]);
+ System.out.println(“~a&b|a&~b = ” + binary[f]);
+ System.out.println(” ~a = ” + binary[g]);
+ }
+ }

در این مثال ، aو bو الگوهای بیتی دارند که کلیه چهار احتمال برای ارقام
دو تایی باینری را معرفی می کنند . ۰-۰، ۰-۱،، ۱-۰،و ۱-۱و . می توانید مشاهده
کنید چگونه |و &و روی هر یک از بیت ها با توجه به نتایج در cو dو عمل می کنند.
مقادیر نسبت داده شده به eو fو مشابه بوده و نشان دهنده چگونگی کار عملگر ^
می باشند . آرایه رشته ای با نام binary معرفی ارقام ۰ تا ۱۵ را بصورت باینری و
قابل خواندن برای انسان نگهداری می کند . در این مثال ، آرایه فوق طوری نمایه
سازی شده تا معرفی باینری هر یک از نتایج را نشان دهد . آرایه طوری ساخته شده
که معرفی رشته ای صحیح یک مقدار باینری n را در binary[n] ذخیره می کند . مقدار ~a
بوسیله عملگر ANDبا oxofا( ۰۰۰۰۱۱۱۱ باینری ) عمل شده تا مقدار آن را به
کمتر از ۱۶ کاهش دهد تا بتوان با استفاده از آرایه binary از آن چاپ گرفت .
اکنون خروجی این برنامه بصورت زیر می باشد :

a=1011
b=0110
a^Eb=0111
a&b=0010
a&b=0101
~a&b^Ea&~b=0101
~a=1100

حرکت به چپ
کلیه بیت های موجود در یک مقدار را به تعداد <<عملگر حرکت به چپ یعنی
دفعات مشخص بطرف چپ منتقل می کند . شکل کلی آن بقرار زیر است :

Value << num

تعداد دفعات مقدار
در ایجا num مشخص کننده تعداد مکانهایی است که بیت های موجود در value باید
کلیه بیت های موجود در یک مقدار مشخص را <<به چپ انتقال یابند . بدین ترتیب
بتعداد مکانهایی که در num مشخص شده بطرف چپ حرکت می دهد . برای هر بار حرکت
به چپ ، بیت high-order ( بیش از حد مجاز ) منتقل شده و از دست خواهد رفت و
یک صفر در طرف راست مقدار ، جایگزین می شود . بدین ترتیب هنگامیکه یک حرکت به
چپ روی یک عملوند int عمل می کند ، بیت های گذشته از مکان ۳۱ از دست خواهند
رفت . اگر عملوند یک long باشد، بیت ها پس از گذشتن از مکان ۶۳ از دست میروند.
هنگامیکه مقادیر byteو shortو را انتقال می دهید ، ارتقائ خودکار انواع در
جاوا نتایج غیر منتظره ای ایجاد می کند . حتما” می دانید که هنگام ارزشیابی
عبارات ، مقادیر byteو shortوبه int ارتقائ می یابند. بعلاوه جواب چنین عبارتی
از نوع int خواهد بود . بنابراین حاصل یک حرکت به چپ روی مقادیر byteو shortو
یک int خواهد بود و بیت های انتقال یافته به چپ تا زمانیکه از مکان بیت ۳۱
نگذرند ، از دست نمی روند . علاوه براین ، یک مقدار منفی byteو shortو هنگامیکه
به int ارتقائ می یابد ، بسط علامت پیدا می کند . بنابراین بیت های بیش از حد
مجاز با بیت ۱ پر می شوند . بخاطر این دلایل ، انجام یک حرکت به چپ روی byte و short
مستلزم آن است که از بایت های بیش از حد مجاز در جواب int دست بکشید .
بعنوان مثال ، اگر یک مقدار byte را حرکت به چپ بدهید ، آن مقدار ابتدا به نوع int
تبدیل شده و سپس انتقال خواهد یافت . باید سه بایت بالایی حاصل را از دست
بدهید . اگر بخواهید حاصل یک مقدار byte انتقال یافته را بدست آورید . باید سه
بایت بالایی حاصل را از دست بدهید . آسان ترین روش برای انجام اینکار استفاده
از تبدیل cast و تبدیل جواب به نوع byte است . مثال بعدی همین مفهوم را برای
شما آشکار می سازد :

+ // Left shifting a byte value.
+ class ByteShift {
+ public static void main(String args[] ){
+ byte a = 64/ b;
+ int i;
+
+ i = a << 2;
+ b =( byte( )a << 2);
+
+ System.out.println(“Original value of a :” + a);
+ System.out.println(“i and b :” + i + ” ” + b);
+ }
+ }

خروجی تولید شده توسط این برنامه بقرار زیر می باشد :

original value of a:64
i and b :256 0

چون برای اهداف ارزشیابی ، a به نوع int ارتقائ یافته ، دوبار حرکت به چپ
مقدار ۶۴ (۰۰۰۰ َ۰۱۰۰) منجر به i می گردد که شامل مقدار ۲۵۶ (۰۰۰۰ َ۱ ۰۰۰۰)
می باشد . اما مقدار b دربرگیرنده صفر است زیرا پس از انتقال ، بایت کمتر از
حد مجاز (loworder) اکنون شامل صفر است . تنها بیت دربرگیرنده ۱ به بیرون
انتقال یافته است .
از آنجاییکه هر بار حرکت به چپ تاثیر دو برابر سازی مقدار اصلی را دارد
برنامه نویسان اغلب از این خاصیت بجای دو برابر کردن استفاده می کنند . اما
باید مراقب باشید . اگر یک بیت ۱ را به مکان بیت بیش از حد مجاز (۳۱ یا ۶۳)
منتقل کنید ، مقدار فوق منفی خواهد شد . برنامه بعدی همین نکته را نشان میدهد.

+ // Left shifting as a quick way to multiply by 2.
+ class MultByTwo {
+ public static void main(String args[] ){
+ int i;
+ int num = 0xFFFFFFE;
+
+ for(i=0; i<4; i++ ){
+ num = num << 1;
+ System.out.println(num);
+ }
+ }
+ }

خروجی این برنامه بقرار زیر خواهد بود : ۵۳۶۸۷۰۹۰۸

۱۰۷۳۷۴۱۸۱۶
۲۱۴۷۴۸۳۶۳۲
- ۳۲

مقدار آغازین را با دقت انتخاب کرده ایم بطوریکه بیت بعد از چهار مکان حرکت
بطرف چپ ، مقدار ۳۲- را تولید نماید . همانطوریکه می بینید ، هنگامیکه بیت ۱
به بیت ۳۱ منتقل می شود ، رقم بعنوان منفی تفسیر خواهد شد .

حرکت به راست
کلیه بیت های موجود در یک مقدار را به تعداد >>عملگر حرکت به راست یعنی
دفعات مشخص بطرف راست انتقال می دهد . شکل کلی آن بقرار زیر می باشد :

value >> num

تعداد دفعات مقدار
در اینجا ، num مشخص کننده تعداد مکانهایی است که بیت های value باید بطرف
کلیه بیت های یک مقدار مشخص شده را به تعداد >>راست انتقال یابند . یعنی
مکانهای بیتی مشخص شده توسط num بطرف راست انتقال می دهد .
کد قطعه ای زیر مقدار ۳۲ را دو مکان بطرف راست منتقل می کند و آنگاه جواب
آن در a معادل ۸ قرار می گیرد :

+ int a = 32;
+ a = a >> 2; // a now contains 8

اگر بیت هایی از یک مقدار به بیرون منتقل شوند ، آن بیت ها از دست خواهند
رفت . بعنوان مثال کد قطعه ای بعدی مقدار ۳۵ را دو مکان بطرف راست منتقل نموده
و باعث می شود تا دو بیت کمتر از حد مجاز از دست رفته و مجددا” جواب آن در a
معادل ۸ قرار گیرد .

+ int a = 35;
+ a = a >> 2; // a still contains 8

همین عملیات را در شکل باینری نگاه می کنیم تا اتفاقی که می افتد ، روشن تر
شود : ۰۰۱۰۰۰۱۱ ۳۵
>> 2
00001000 8

هر بار که یک مقدار را به طرف راست منتقل می کنید ، آن مقدار تقسیم بر دو
می شود و باقیمانده آن از دست خواهد رفت . می توانید از مزایای این روش در
تقسیم بر دو اعداد صحیح با عملکرد سطح بالا استفاده نمایید . البته ، باید مطمئن
شوید که بیت های انتهایی سمت راست را به بیرون منتقل نکنید .
هنگامیکه حرکت بطرف راست را انجام می دهید ، بیت های بالایی ( از سمت چپ )
در معرض حرکت بطرف راست قرار گرفته ، با محتوی قبلی بیت بالایی پر می شوند .
این حالت را بسط علامت (sign extension) نامیده و برای محفوظ نگهداشتن علامت
ارقام منفی هنگام حرکت بطرف راست استفاده می شوند. بعنوان مثال ۱>>8- معادل ۴-
است که به شکل باینری زیر می باشد : ۱۱۱۱۱۰۰۰- ۸
>> 1
11111100- 4

جالب است بدانید که اگر ۱- را بطرف راست حرکت دهید، حاصل آن همواره ۱- باقی
می ماند ، چون بسط علامت ، مراقب آوردن یک بیت دیگر در بیت های بیش از حد مجاز
خواهد بود .
گاهی هنگام حرکت بطرف راست مقادیر ، مایل نیستیم تا بسط علامت اجرا شود .
بعنوان مثال ، برنامه بعدی یک مقدار نوع byte را به معرفی رشته ای در مبنای ۱۶
تبدیل می کند . دقت کنید که مقدار منتقل شده با استفاده از عملگر ANDیا oxofا
پوشانده شده تا هر گونه بیت های بسط یافته علامت را بدور اندازد بطوریکه مقدار
فوق را بتوان بعنوان یک نمایه به آرایه ای از کاراکترهای در مبنای ۱۶ استفاده
نمود .

+ // Masking sign extension.
+ class HexByte {
+ static public void main(String args[] ){
+ char hex[] = {
+ ’0′/ ’1′/ ’2′/ ’3′/ ’4′/ ’5′/ ’6′/ ’7′/
+ ’8′/ ’9′/ ‘a’/ ‘b’/ ‘c’/ ‘d’/ ‘e’/ ‘f’
+ };
+ byte b =( byte )oxf1
+
+ System.out.println(“b = ox” + hex[(b >> 4 )& oxof] + hex[b & oxof]);
+ }
+ }

خروجی این برنامه بقرار زیر می باشد :

b=oxf1

حرکت به راست فاقد علامت
بطور خودکار >>اکنون می دانید که هر بار یک انتقال اتفاق می افتد ، عملگر
جای خالی بیت بیش از حد مجاز را با محتوی قبلی اش پر می کند . این عمل سبب حفظ
علامت آن مقدار می گردد . اما گاهی تمایلی برای اینکار نداریم . بعنوان مثال
می خواهید چیزی را منتقل کنید که معرف یک مقدار عددی نیست . بالطبع نمی خواهید
عمل بسط علامت انجام گیرد . این حالت هنگام کار با مقادیر براساس پیکسل (pixel)
و گرافیک اغلب وجود دارد . در چنین شرایطی لازم است تا مقدار صفر در بیت بیش از
حد مجاز قرار گیرد ، صرفنظر از اینکه مقدار قبلی در آن بیت چه بوده است . این
حالت را انتقال فاقد علامت (usigned shift) می گویند. برای این منظور، از عملگر
استفاده کنید که صفرها را در بیت بیش >>>حرکت به راست فاقد علامت در جاوا یعنی
از حد مجاز منتقل می کند .
می باشد . در اینجا >>>کد قطعه ای زیر نشان دهنده عملگر a معادل ۱- است که
کلیه ۳۲ بیت را در باینری روی ۱ تنظیم می کند . این مقدار سپس ۲۴ بیت بطرف
راست انتقال می یابد، و ۲۴ بیت بالایی را با صفرها پر می کند و بسط علامت معمولی
را نادیده می گیرد . بدین ترتیب a معادل ۲۵۵ می باشد . + int a =- 1;
+ a = a >>> 24;

اینجا همان عملیات را در شکل باینری مشاهده می کنید تا بهتر بفهمید چه
اتفاقی افتاده است : ۱
در باینری بعنوان یک int 11111111 11111111 11111111 11111111 >>>24
255
در باینری بعنوان یک int َ۱۱۱۱۱۱۱۱ ۰۰۰۰۰۰۰۰ ۰۰۰۰۰۰۰۰ ۰۰۰۰۰۰۰۰
اغلب اوقات آنچنان سودمند که بنظر می رسد ، نبوده چون فقط برای >>>عملگر
مقادیر ۳۲ بیتی و ۶۴ بیتی معنی دارد . بیاد آورید که مقادیر کوچکتر در عبارات
بطور خودکار به int ارتقائ می یابند . بدین ترتیب بسط علامت اتفاق افتاده و
حرکت بجای مقادیر ۸ بیتی و ۱۶ بیتی روی مقادیر ۳۲ بیتی انجام می شود . یعنی
باید انتظار یک حرکت به راست فاقد علامت روی یک مقدار byte داشته باشیم که در
بیت ۷ ، صفر را قرار می دهد . اما واقعا” اینطور نیست ، چون در واقع مقدار ۳۲
بیتی است که منتقل می شود . برنامه بعدی این تاثیری را نشان می دهد .

+ // Unsigned shifting a byte value.
+ class ByteUShift {
+ static public void main(String args[] ){
+ char hex[] = {
+ ’0′/ ’1′/ ’2′/ ’3′/ ’4′/ ’5′/ ’6′/ ’7′/
+ ’8′/ ’9′/ ‘a’/ ‘b’/ ‘c’/ ‘d’/ ‘e’/ ‘f’
+ };
+ byte b =( byte )oxf1
+ byte c =( byte( )b >> 4);
+ byte d =( byte( )b >>> 4);
+ byte e =( byte(( )b & oxff )>> 4);
+
+ System.out.println(” b = ox”
+ + hex[(b >> 4 )& oxof] + hex[b & oxof]);
+ System.out.println(” b >> 4 = ox”
+ + hex[(c >> 4 )& oxof] + hex[c & oxof]);
+ System.out.println(” b >>> 4 = ox”
+ + hex[(d >> 4 )& oxof] + hex[d & oxof]);
+ System.out.println(“(b & oxof )>> 4 = ox”
+ + hex[(e >> 4 )& oxof] + hex[e & oxof]);
+ }
+ }

چگونه هنگام کار با بایت ها عملی >>>خروجی این برنامه نشان میدهد که عملگر
انجام نمی دهد . متغیر b بعنوان یک مقدار byte منفی قراردادی در این نمایش
تنظیم شده است . سپس مقدار byteدر bر که چهار مکان بطرف راست انتقال بافته به C
منتسب می شود که بخاطر بسط علامت مورد انتظار oxff است . سپس مقدار byteدر bر
که چهار مکان بطرف راست و فاقد علامت منتقل شده به d منتسب می شود که انتظار
دارید oxof باشد ، اما در حقیقت oxff است چون بسط علامت هنگامیکه b به نوع int
قبل از انتقال ارتقائ یافته اتفاق افتاده است . آخرین عبارت ، e را در مقدار byte
متغیر b که با استفاده از عملگر ANDبا ۸ا بیت پوشانده شده تنظیم نموده و
سپس چهار مکان بطرف راست منتقل می کند که مقدار مورد انتظار oxof را تولید
می کند . دقت کنید که عملگر حرکت به راست فاقد علامت برای d استفاده نشد ، چون
حالت بیت علامت بعد از AND شناخته شده است .

b=oxf1
b>>4=oxff
b>>>4=oxff
( b&oxff)>>4=oxof

انتسابهای عملگر رفتار بیتی
کلیه عملگرهای رفتار بیتی باینری یک شکل مختصر مشابه باعملگرهای جبری دارند
که عمل انتساب را با عملیات رفتار بیتی ترکیب می کنند. بعنوان مثال ، دو دستور
بعدی که مقدار a را چهار بیت به راست حرکت می دهند ، معادل یکدیگرند :

+ a = a >> 4;
+ a >>= 4;

بطور مشابه ، دو دستور زیر که a را به عبارت روش بیتی aoRb منتسب می کنند
معادل یکدیگرند :

+ a = a | b;
+ a |= b;

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

+ class OpBitEquals {
+ public static void main(String args[] ){
+ int a = 1;
+ int b = 2;

دیدگاه خود را بیان کنید.

باید وارد سایت شده باشید برای دیدگاه دادن