PDA

View Full Version : مبتدی: ارتقاء نوع short و byte به int و طرح یک مشکل



قله بلند
شنبه 07 آذر 1388, 13:26 عصر
با سلام

در جاوا وقتی روی متغیرهای نوع short و byte عملی انجام شود به صورت خودکار به int ارتقا پیدا می کنند یعنی هرگاه دو مقدار از نوع byte در هم ضرب شوند جواب این ضرب به صورت خودکار به int ارتقا پیدا می کند مگر اینکه با عمل casting جلوی این کار گرفته شود. مثلاً:
Byte a=5,b=2,c;
C=(byte)a*b; سوال: حالا سوال من اینجاست. لطفاً به عبارت زیر توجه کنید:
Byte a=0x05;
System.out.println(a); که جوابش می شود عدد 5. تا اینجا همه چیز منطقی است ولی حالا به عبارت زیر توجه نمایید:
Byte a=(byte)0xfb;
System.out.println(a); که جوابش می شود عدد 5-. مگر عدد 5- در فاصله 127 تا 128- نیست. پس عمل casting چرا می خواهد؟(اگر از casting استفاده نکنم خطای تبدیل انواع را می گیرد) پس چرا وقتی به جای عدد 5 نوشتم 0x05 از casting استفاده نکردم و جواب هم درست بود؟ حالا به عبارت زیر دقت نمایید:
Byte a=-5;
System.out.println(a); در این حال عدد 5- چاپ می شود. بدون عمل casting . چرا اینگونه می شود؟ واقعاً گیج شدم.

persianshadow
شنبه 07 آذر 1388, 15:54 عصر
خب در مورد اول مشکلی وجود داره و اینکه با typecasting کردن هم متغییر c از نوع byte نخواهد شد
و این کد همراه با خطا خواهد بود باید حتمآ c از نوع int باشه به یک دلیل زیرا بر خلاف گفته شما بعد از ضرب
این دو مقدار byte نتیجه int نخواهد شد بلکه هنگامی که دو مقدار byte در هم ضرب می‌شوند قبل از ضرب
شدن نوع آنها در واقع extend شده و به int تبدیل می‌شود یعنی اینکه شما باید مقداری int داشته باشید
و با typecasting هم خطا دریافت خواهید کرد.

در مورد گزینه آخر چرا منفی 5 چاپ نشه ؟ شما یک متغییر دارید از نوع بایت که هیچ عملی هم روی اون
انجام نمی‌شه پس همونطوری که هست باقی می‌مونه.

نکته:

مقادیر byte و short در حین عمل ضرب و قبل از حاصل شدن نتیجه نوعشان به مقداری int ارتقا پیدا
می‌کند.

قله بلند
شنبه 07 آذر 1388, 17:06 عصر
با سلام.
دوست عزیز، این کدها همگی اجرا شده نوشته شده اند و هیچگونه خطای کامپایلری ندارند. در مورد کد اول، اگر من از (byte) استفاده نمی کردم، خطا صادر می شد که دقیقاً این را هم امتحان کردم و نتیجه را دیدم ولی با casting کردن، نتیجه از int به byte تنزل کرد و دیگر خطایی صادر نشد.
در مورد کد دوم، دقیقاً کلام شما صحیح است چون هیچ عملی جز انتساب انجام نمی شود و فقط باید طرف راست انتساب عددی از نوع byte باشد تا با متغیر a سازگاری کند که عدد 0x05 همینگونه است. تا اینجا نیز تمام برنامه به خیر و خوبی تمام شد و نتیجه 5 چاپ شد.
مشکل از اینجا شروع شد که 0xfb عدد 5- است و 5- هم در فاصله 127 تا 128-قرار دارد ولی تا از (byte) استفاده نکنم، خطا صادر می کند که نمی تواند مقدار int را به byte منتسب کند. واقعاً این مساله برایم گیج کننده است. من که فقط یک عمل انتساب انجام دادم و عددی را به a منتسب کردم که در محدوده byte قرار دارد. پس این معضل از کجا سرچشمه می گیرد؟
در کد آخر، من همان عدد 5- را به a منتسب می کنم، ولی دیگر احتیاجی به casting ندارم و هیچ خطایی نیز صادر نمی شود و عدد 5- چاپ می شود.

سوال: مگر 5- با 0xfb چه فرقی با هم دارند که یکی محتاج casting و دیگری فارغ از این ماجراست؟

persianshadow
شنبه 07 آذر 1388, 19:26 عصر
نسخه JDK شما چند هست ؟

persianshadow
شنبه 07 آذر 1388, 19:51 عصر
تکه کد کاملی که بخش اول رو اجرا می‌کنه هم لطفآ اضافه کنید تا خود من کامپایل کنم.
کد اول شما با این شکل نوشتن باید خطا بده.

قله بلند
یک شنبه 08 آذر 1388, 10:58 صبح
با سلام.
من از jdk1.2 استفاده می کنم.
فقط یک عذرخواهی و آن اینکه در پست اول و در قطعه کد اول یادم رفته بود پرانتز بگذارم یعنی(a*b). قطعه کدی که اجرا کردم در ادامه آمده است.
public class A{
public static void main(String args[])
{
byte a=5,b=2,c;
c=(byte)(a*b);
System.out.println("c is="+c);
}
}

persianshadow
یک شنبه 08 آذر 1388, 12:49 عصر
خب در مورد اولی پس دیدید که پرانتز رو جا گذاشته بودید :).

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

خب چند تا نکته :

1 - در برنامه نویسی تا حد امکان باید از typecasting کمتری استفاده کنید.


2 - عددی که شما نوشتید یعنی 0xfb برابر با منفی 5 نیست بلکه این عدد 251 هست ! برای همین چون

از -128 تا 127 بیشتر هست به شما خطا میده و شما با typecasting همه چیز رو به شکل اشتباهی درست

می‌کنید.


3 - عدد درست منفی 5 در مبنای هگزادیسمال برابر با کد زیر هست :



-0x5


خب حالا عدد بالا رو بزارید و ببینید که بدون typecasting عدد منفی 5 چاپ می‌شه.

قله بلند
یک شنبه 08 آذر 1388, 17:34 عصر
با سلام</p>طریقه تولید مکمل دوی یک عدد:

مثلاً عدد 127-:اول: مبنای دوی عدد 127 را محاسبه می کنیم که می شود 01111111 که به صورت هگزا می شود 0x7f .
دوم: مکمل یک عدد حاصل به اضافه عدد 1 که می شود مکمل دوی عدد 127 که می شود 10000001 که به صورت هگزا می شود 0x81 . حالا ما عدد 127- را داریم. درست است؟
وقتی من می نویسم byte a=0x7f دقیقاً عدد 127 چاپ می شود و وقتی می نویسم byte a=-0x7f نیز دقیقاً عدد 127- چاپ می شود. پس 0x81 چه می شود ؟ مگر من مکمل دوی عدد 127- را اشتباه حساب می کنم؟
واقعاً گیج شدم.

persianshadow
یک شنبه 08 آذر 1388, 22:55 عصر
خب بهترین روش همونی هست که خودت هم گفتی یعنی استفاده از هگزادسیمال



byte a=-0x7f


برای نمایش -127 به صورت هگزادسیمال باید بنویسی




byte a=0xffffff81



کد بالا را امتحان کن تا عدد -127 چاپ بشه.باید توجه کنی که فرضآ عدد 5 در باینری به صورت 0101 می‌شه

خب حالا -5 می‌شه : 1011 خب شما به این میگی -5 ولی اینو می‌شه چه عدد دیگه‌ای خوند ؟ 11 .

فقط به صرف دونستن رقم 1 سمت چپ فهمدیم منفی هست.این جور تبدیل‌ها مشکل ایجاد می‌کنه

وقتی رقم رو به hex میبری و روش درست همون کد اول هست.

قله بلند
یک شنبه 08 آذر 1388, 23:27 عصر
من واقعاً شگت زده شدم. بله دقیقاً عدد 127- چاپ شد در حالیکه از casting نیز استفاده نکردم.
چی شد؟ چرا اینجوری شد؟ این 6 تا f انگار معجزه کرد! با وجود این 6 عدد f طول کلمه من به 4 بایت رسید یعنی طول int .
شما در این لحظه درب جدیدی به روی من باز کردید . من تا به حال چنین چیزی را در c++ ندیده بودم. لطفاً پرده از این راز بردارید تا شیرینی اش دوصد چندان شود.

قله بلند
دوشنبه 09 آذر 1388, 16:01 عصر
با سلام
جناب persianshadow عزیز
اگر لطف بفرمایید و به پست قبلی پاسخ دهید ممنون می شوم چون واقعاً پاسخش را نمی دانم و از طرفی هم جوابش برایم جالب است.
ثانیاً برای کامل کردن این تاپیک و شروع سوال بعدی در تاپیکی دیگر علت [در برنامه نویسی تا حد امکان باید از typecasting کمتری استفاده کنید] را بیشتر توضیح دهید.
با تشکر فراوان