الدرس الثالث و الأربعون
(43)
Variable Types & Kinds
4-1 :Primitive Types
نختتم هذا الجزء حول أنواع التعريف الأساسية "" بالنوعين double و float و كما
هو معلوم هذان النوعان يتعاطيان مع القيم ذات الصيغة الكسرية أو العشرية مثل 2.0001
أو 6.023 أو 2.0000
لهذين النوعين فوائد لاتوجد في الأنواع الأخرى حول التعامل مع الأرقام وخصوصاً
الكبيرة منها. هل تعرف عدد افوغادرو؟ هل تعرف حجم الكرة الأرضية أو وزنها؟
قبل التطرق للفوائد سنناقش بعض الزوائد --- انظر للجدول التالي: "مقتبس من الدرس السابق" :
Type bitsize Range -----
float 32 bits <2128
double 64 bits <21024
بالنسبة لنوع float سيكون عدد الخانات بالنظام الثنائي 32 خانة(يشبه int). و بالنسبة ل double سيكون 64 خانة (يشبه long )
ولكن ماهو أعلى رقم ممكن أن نجده بإستخدام لغة الجافا؟
إذا كان المتغير من نوع double فإن أعلى رقم هو:
1.79769313486231570E308 = 1.79769313486231570x10308 < 21024
و أصغر عدد موجب صحيح قبل الصفر يمكن تمييزه هو:
4.9406564581246544E-324 = 4.9406564581246544x10-324
بينما إذا صرح عن المتغير ليكون من نوع float فإن أعلى رقم موجب ممكن الحصول
عليه هو:
3.40282347E38 = 3.40282347x1038 < 2128
وأيضاً أصغر رقم موجب صحيح هو:
1.40239846E-45 =1.40239846x10-45
هل تخيلت الرقم الأول؟ و هل رأيت كيف تمت كتابته؟
فالقيم من نوع double تتكون من 309 خانة عشرية(308+1) ولكن لصعوبة كتاباتها و
للتوفير في المساحة التي ستشغل من ذاكرة الكمبيوتر لتخزين هذا الرقم المهول فإنها
تكتب بالصورة الأسية و ذلك بإستخدام الحرف E و هو
م
ختصر Exponent التي تعني
"أس"
تخيل لدينا عدداُ كبيراً يتألف من 7 و الى يساره 40 صفراً كما هو ممثل
بمايلي:
70000,000000000000,000000000000,000000000000
هل تخيلت جسامة هذا الرقم؟ إنه يُنطَق سبعين الف تريليون تريليون تريليون(ركز على الفواصل). أو سبعين الف كنتليون كنتليون(ركز على الألوان )
في الأعداد الصحيحة --- تحديداً long -- فإن أعلى رقم نحصل عليه حسب النظام
العشري يتألف من 19 خانة. بينما الرقم السابق يتألف من 41 خانة. لذا لايمكن
تعريفه الا باستخدام أمر double
تخيل لدينا العدد التالي الصغير جداً مقارنة بالعدد الجسيم السابق:
9,999,999
هذا الرقم كتب بالصورة الرياضية المعروفة و الفواصل فقط لمعرفة الرقم بسرعة من
خلال معرفة عدد الخانات ---- هذا الرقم أقل من 10 مليون ب 1 --- أي أنه 9
مليون و 999 الف و 999
لو أضفنا عليه 1 سيكون 10 مليون على النحو التالي:
9,999,999+1 = 10,000,000
كلا الرقمين قد يمثلان كما سبق أو بإستخدام الأس من أجل توفير الفراغ على
النحو التالي:
9,999,999 = 9.999999x106
10,000,000 =10.0x106 = 1.0x107
أعتقد أن الأمور واضحة حتى الأن --- فأين المشكلة؟
طبعاً نقصد بالمشكلة كيف سيطبع برنامج الجافا الأرقام العشرية. هل بالصورة
الأسية أم بالصورة الرياضية المعروفة؟
جواب: يعتبر الرقم 9,999,999 (سبع خانات) هو الحد الفاصل بين الطباعة بالصورة
المعروفة و الطباعة بالصورة الأسية --- فالرقم السابق مجرد أن نضيف اليه 1 سيتكون
من 8 خانات و ليس 7 --- بإمكانك عد خانات الرقم 10 مليون السابق ---- أي عندما يصبح
عدد خانات الرقم ادينا 8 فإن عرض الرقم سيكون بالصورة الأسية على النحو التالي:
1.0E7=1x10000000 = 1.0x107
لا شك أنك أدركت أن الحرف E يعني "10 أس"
واختصاراً لو كان عدد خانات الرقم لدينا 7 أو أقل فإن البرنامج سيعرضه كما هو
ولكن لو تجاوز عدد الخانات 7 فإنه سيعرض بالصورة الأسية --- انظر للبرنامج التالي و
الذي كتبناه ليطبع عددين أحدهما هو 9999999 و الأخر هو 10000000
class DoubleEaxample
{
public static void main(String[] args)
{
double x,y;
x=9999999;
System.out.println("x = "+x);
y=x+1;
System.out.println("y = "+y);
}
}
x = 9999999.0
y = 1.0E7
Press any key to continue...
الان سنكتب برنامجاً بسيطاً لمجرد عرض رقم ما و هذا الرقم هو:
12345678901234567901234567890.0
واضح أن الجزء الصحيح لهذا الرقم يتألف من 30 خانة فهل سيكتبه البرنامج على
النحو التالي(7 خانات و هي السعة الأعلى على يسار الفاصلة كما ذكرنا و البقية على
اليمين):
1234567.89012345678901234567890E23
ام على هذا النحو(رقم واحد على يسار الفاصلة و البقية في الجزء
الكسري 
:
1.23456789012345678901234567890E29
أم سيكون بصورة أخرى؟
الحقيقة أن الجواب سيكون مشابه للنموذج الثاني أي رقم واحد على يسار الفاصلة و
البقية تختزل من خلال الأس ولكن سيتم تقريب الجواب لأقرب 16 خانة بدلاً من 29 خانة
بعد الفاصلة حيث سيتم التخلص من الخانات الزرقاء في العدد السابق --- ستكون
محصلة برنامجنا على النحو التالي:
1.2345678901234567E29
سنتأكد من شرحنا هذا باستخدام البرنامج التالي:
class DoubleEaxample
{
public static void main(String[] args)
{
double x;
x=12345678901234567901234567890;
System.out.println("x = "+x);
}
}
x = 1.2345678901234568E29
Press any key to continue...
لاحظ في الجواب النهائي أن 8 كتبت بدلاً من 7 (انظر للرقم 8 باللون الأصفر) و
السبب هو التقريب العشري حيث تم تقريب ال 7 الى 8 لأن العدد على يمين 7 وهو 8 و
الذي تم التخلص منه أكبر من 5 و بالتالي تم التقريب.
ذكرناً في بداية الدرس أن أعلى قيمة يتم تمثيلها بإستخدام double تتألف من 309
خانة و هذا الرقم تحديداً هو:
1.7976931348623157E308
لو غيرنا الرقم 57 باللون الأحمر الى 59 (إضافة بسيطة)--- فإن
الكمبيوتر سيصاب بالغثيان ولن يفهم الرقم لأنه خارج الخدمة الممكن تقديمها --
فالرقم السابق هو أفضل الموجود و الرقم التالي هو بداية الغثيان حيث سينتج
لديك رسالة تنبيه لخطأ بعد compile
1.7976931348623159E308
ضع هذا الرقم كقيمة للمتغير x في البرنامج السابق سينتج لديك الرسالة التالية:
--------------------Configuration: JDK version 1.3.1_01 Default--------------------
C:\Documents and Settings\User\Desktop\J\abc.java:6: floating point number too large
x=1.7976931348623159E308;
^
1 error
Process completed.
و بما أن هناك خطأ فلايمكن تنفيذ البرنامج. و إن تم تنفيذه بالصدفة و بالصدفة
كان لديك ناتجاً ما --- فاعتبر هذه القيمة أتت من الواق واق أو خرجت من فم سمكة
تسبح في بحيرة البجع.
لاتنسى أن تلحق القيم من نوع double بالحرف D أو d بعد نهاية الرقم و القيم من
نوع float بالحرف f أو F و لكي لا ننسى القيم من نوع long يمكن الحاقها بالحرف L أو
l كما في الأمثلة التالية:
long x= 78L;
float d=1.2f, d2 = 3.33F;
double y = 1.23D, y2 = 1.2635E-45D, y3 = 4.7E-6d;
علامة الأس العشري E قد تكتب صغيرة أو كبيرة -- أي E أو e كما في المثال التالي:
double y2 = 1.2635E-45, y3 = 1.2635e-6;
يتبقى كيفية تمثيل الرقم من نوع float أو double داخل ذاكرة الكمبيوتر و التي
لاتعرف سوى لغة 1 أو 0 و من الجدول السابق نعرف كم عدد الخلايا التي سيحجزها كل نوع
فعندما يتم تعريف المتغير ليكون من نوع float فإنه سيتم حجز 32 خلية لتخزين
هذا الرقم بينما سيتم حجز 64 خلية لو كان المتغير من نوع double و ليست القضية
سلسة هنا لوجود الأس أو الفاصلة و لاننسى مانسيناه في الدرس السابق وهو أن أول خلية
تمثل الإشارة فإذا كانت اشارة الرقم + تملاً أول خلية بالصفر و إذا كانت الإشارة
-(سالب) تملأ اول خلية بالرقم 1 ---- بقية الخلايا لتمثيل الرقم نفسه.
float binary representation --
للقراءة فقط
تمثيل القيم من نوع float يعتمد على تصنيف IEEE Floating-Point Standard
754 و الذي يدرس كيفية تحويل العدد من نوع float الى عدد ثنائي مفهوم ---
ذكرنا أن هذا النوع يستغل 32 خلية متجاورة وكل خلية تحمل إما 0 أو 1 --- سنفترض أن
جميع الخلايا مدبئياً فراغة على النحو التالي:
00000000000000000000000000000000 : عدد الخلايا 32
الخانة الأولى محجوزة للإشارة(خانة واحدة) و الخانات
من 2 الى 9 محجوزة للأس(8 خانات) و الخانات من 10 الى
32 محجوزة للجزء العشري(23 خانة). قارن بين الألوان
الان تخيل ان العدد لدينا من نوع float هو:
0.5
الإشارة موجبة لذلك أول خانة ستكون 0 و ليس 1 --- هذا العدد يجب أن يكتب أولاً بالصورة الأسية و
ذلك على النحو التالي:
0.5 =1/2 = 1.0x2-1
لاحظ أن الأساس هو 2 و الأس -1 ----- هذا الأس سيشغل الخانات من 2 الى 9 --- فما
هو المقابل الثنائي للعدد -1؟
لأن النوع لدينا double و للتخلص من الناقص فإننا نضيف اليه العدد 127 كما تم
تعريف ذلك من خلال المقياس العالمي IEEE-Standard سيصبح المكافئ الأسي ل -1 هو 127
- 1 = 126
126 مجرد رقم عشري و من السهل تحويله الى رقم ثنائي (-1 و 126 تعتبر نفس
الشئ) و ذلك على النحو التالي:
-1 + 127 = 126 = 01111110
حتى هذه اللحظة تم ملئ الخانات من 1 الى 9 و أصبح الرقم الثنائي هو:
00111111000000000000000000000000
بقية الخانات و كما ذكرنا محجوزة للجزء العشري "الكسري" وهو 0 في حالتنا هذه --- انظر للصفر باللون الأخضر
في سطر سابق و نعيده هنا:
0.5 =1/2 = 1.0x2-1
و هذا يقتضي أن جميع الخانات الباقية يجب أن تملاً بالصفر. و سيكون الرقم مرتباً
في ذاكرة الكمبيوتر على النحو التالي:
0.5 = 00111111000000000000000000000000
غني عن القول أن مكان النقطة "الفاصلة" سيكون
بين اللون الأزرق و البني و للتوضيح فقط:
0.5 = 001111110.00000000000000000000000
لو كان الرقم -0.5 --- بالسالب --- فقط غير الصفر الأحمر الى 1 و ذلك على النحو
التالي:
-0.5 = 101111110.00000000000000000000000
الأمثلة التالية إضافية و عليك إثباتها
و الأجوبة مؤكدة:
1.0 = 001111111.00000000000000000000000
1.5 = 011111111.10000000000000000000000
6.5 = 010000001.10100000000000000000000
10.65 = 010000010.01010100110011001100110
ماذا عن القيم من نوع double؟
نفس الإجراءات السابقة و لكن هنا الدقة ستكون مزدوجة "double precsion" على عكس نوع float و الذي كانت الدقة فيه
احادية "single-precsion"
الخانة الأولى للإشارة و الخانت ال 11 التالية للأس و بقية الخانات (52 خانة)
محجوزة للجزء الكسري. و المجموع هو 64 خانة على النحو المبدئي التالي:
0000000000000000000000000000000000000000000000000000000000000000
لا أنصحك بعدها فهي 64 خانة. سنعيد مثالنا السابق على افتراض أن القيمة 0.5 تم
تعريفها في متغير من نوع double ---- الإشارة موجبة --> أول خانة تملاً بالصفر
--- الأس هو نفسه بعد التحويل و يساوي سالب واحد -1 ---> بدلاً من 127 نستخدم
1023 ---> إذن
-1 + 1023 = 1022
بتحويل 1022 اللا النظام الثنائي :
1022 = 01111111110
بقية الخانات صفر لأن الجزء العشري يساوي 0. و بناءً عليه سيكون 0.5 على النحو
التالي ثنائياً:
0.5 = 0011111111100000000000000000000000000000000000000000000000000000
أمثلة أخرى:
4.0 = 0100000000010000000000000000000000000000000000000000000000000000
4.5 = 0100000000010010000000000000000000000000000000000000000000000000
5.0 = 0100000000010100000000000000000000000000000000000000000000000000
5.5 = 0100000000010110000000000000000000000000000000000000000000000000
-5.5 = 1100000000010110000000000000000000000000000000000000000000000000
10.0= 0100000000100100000000000000000000000000000000000000000000000000
لمعرفة المزيد حول تحويل الأرقام العشرية "الكسرية" الى لغة الكمبيوتر
ابحث في الانترنت عن مواضيع تحتوي على العناواين التالية و ذلك من خلال
إحدى محركات البحث الشهيرة و لاتنسى أن الجزء الأخير للقراءة ة الثقافة العامة حول
جزئية بسيطة في فهم ذاكرة الكمبيوتر لأحد اجزاء البرنامج. و هي قد تبدو صعبة في
البداية ولكنها ممتعة و مشوقة بعد أن تنغمس فيها قليلاً.
IEEE-754 Floating-Point Conversion: From Decimal Floating-Point To 32-bit and
64-bit Hexadecimal Representations Along with Their Binary Equivalents
الدرس القادم حول reference
types
ـ ــ أشلاءــ ـو مـ الكلمةـ ـاجاورها