تعلّم البرمجة بلغة كوتلن (16): أنواع العدد Number Types

تعلّم البرمجة بلغة كوتلن (16): أنواع العدد Number Types
أستمع الى المقال

تحدثنا في درس أنواع البيانات الأساسية في كوتلن، عن تقسيمات النوع Number. ولأهمية التعامل مع الأعداد في البرمجة عمومًا، سنتحدث في هذا الدرس بطريقة أشمل عن التعامل مع هذه الأعداد، وكيفية إجراء العمليات الحسابية عليها، وتجنب الأخطاء التي قد نقع فيها، عند استخدامنا لها في برامجنا.

العوامل الحسابية الأساسية:

تستخدم كوتلن – مثل معظم لغات البرمجة – الرموز أو العوامل الحسابية الأساسية للأعداد، مثل:

  • الجمع (+) Addition.
  • الطرح (-) Subtraction.
  • القسمة (/) Division.
  • الضرب (*) Multiplication.
  • باقي القسمة (%) Modulo.

ترتيب العمليات الحسابية:

عند إجراء العمليات الحسابية على الأعداد، ودمج عدة عوامل حسابية في تعبير واحد، تتبع لغة كوتلن ترتيب شبيه بالترتيب والأسبقية للعوامل الحسابية في علم الرياضيات. ويكون الترتيب كالتالي:

  • الأقواس ( ).
  • الضرب * والقسمة / .
  • باقي القسمة %.
  • الجمع + والطرح – .

فمثلًا، إذا كان لدينا تعبير يستخدم عدة عوامل، ونريد من كوتلن تنفيذه وطباعة النتيجة، كالتالي:

في التعبير أعلاه ستقوم كوتلن أولًا بعملية القسمة لأن لديها الأولوية. ثم ستجد أن هناك عاملين لديهما نفس الأولوية، وهما الجمع والطرح. هنا العامل على اليسار لديه الأولوية على اليمين، لذا ستقوم بالجمع أولًا لأنه على يسار التعبير، وأخيرًا الطرح. ليكون الناتج: 6.

وستتعامل كوتلن مع عاملي  الضرب والقسمة إذا أتيا معًا في تعبير، بنفس طريقة الجمع والطرح، أي الأولوية ستكون لمن يوجد على اليسار.

ولكن، إذا أردنا في التعبير أعلاه تنفيذ الجمع أولًا، فيمكننا بكل بساطة وضعه في قوس، فالأقواس لديها الأولوية الأولى لذا ستنفذها كوتلن أولًا، كالتالي:

وفي هذه الحالة سيكون ناتج الطباعة هو: 2. وإذا كان لدينا عامل باقي القسمة في التعبير،  فالعملية التي يقوم بها، سيتم تنفيذها بعد الأقواس والضرب والقسمة، ولكن قبل الجمع والطرح.

باقي القسمة:

إذا كان لدينا عددين تم إسنادهما كقيمة لمتغيرين num1 و num2، وأجرينا عملية القسمة بباقي على العددين، وأسندنا القيمة الناتجة من القسمة إلى متغير ثالث، كالتالي:

سيكون ناتج الطباعة من البرنامج أعلاه هو الرقم: 7. لأن تقسيم 17 على 10 سيكون الناتج 1 والباقي 7، والباقي هو ما يهمنا عند استخدام العامل (%).

قسمة العدد الصحيح Int:

عند استخدام عامل القسمة (/) بدلًا عن عامل القسمة بباقي (%) في البرنامج السابق، كالتالي:

سيكون ناتج الطباعة من البرنامج أعلاه هو الرقم: 1، بالرغم من أن الناتج هو: 1.7. أي واحد فاصل سبعة، أين ذهب الرقم 7 بعد الفاصلة العشرية؟

حسنًا كما عرفنا من درس أنواع البيانات، تستنتج كوتلن نوع المتغير عند إعلانه. وهنا تعرفت كوتلن على القيم للمتغيرين على أنها من نوع عدد صحيح Int. وعند تقسيم عدد صحيح Int على عدد صحيح Int، سيتم تجاهل الأرقام بعد الفاصلة العشرية تمامًا وطباعة ما قبل الفاصلة. هذه هي الطريقة القياسية عند التعامل مع الأعداد الصحيحة من نوع Int.

لفهم ما يمكن أن يسببه عدم استخدام النوع المناسب عند العمل مع الأعداد، دعونا نقوم ببناء برنامج بسيط نضع به هذه المفاهيم، وليكن برنامج لحساب كتلة جسم الإنسان ومعرفة هل وزنه مناسب أم لا.

برنامج قياس الوزن الصحي للجسم:

لمعرفة ما إذا كان شخص بالغ (من سن 18 إلى 65) يمتلك وزنًا مناسبًا أو العكس، يمكننا استخدام حساب مؤشر كتلة الجسم (Body Mass Index (BMI. والمعادلة المستخدمة في هذا الحساب هي:

BMI = KG / M2

مؤشر كتلة الجسم = الوزن بالكيلوجرام مقسوم على مربع الطول بالمتر.

فإذا عرفنا وزن وطول الشخص وعوضناهما في المعادلة، وكان ناتج العملية أقل من 18.5، فالشخص يعاني نقص الوزن Underweight. ما بين 18.5 و 24.9 يعتبر هو الوزن الطبيعي Normal weight. أما إذا كان الناتج أكثر من 25 فما فوق يعني أن هذا الشخص يعاني من زيادة الوزن Overweight.

لدينا المعادلة وعرفنا طريقة الحساب، كل ما علينا الآن هو جعل برنامجنا يستقبل وزن الشخص بالكيلوغرام وطوله بالمتر وتطبيقهما على المعادلة. لفعل ذلك، سنقوم أولًا بإنشاء دالة تحسب لنا الوزن، وليكن اسمها bmi لتدل على مهمتها، كالتالي:

قمنا بإنشاء دالة كما شرحناها في درس الدوال، ووضعنا لها معاملين من النوع Int واللذين ستحتاجهما الدالة للقيام بالحساب، وهما الوزن weight، والطول height. ووضعنا النوع الذي ستعيده الدالة صراحة، وهو عبارة عن النص String الذي سيخبرنا بحالة وزن الشخص. ثم أعلنا عن متغير لحساب الوزن باستخدام المعادلة وحفظنا النتيجة في متغير أسميناه bmi. واستخدمنا تعبير if الشرطي ليعيد لنا النص المناسب حسب قيمة المتغير bmi، وأخيرًا ستعيد الدالة النتيجة العائدة من تعبير if، باستخدام كلمة return.

استدعاء الدالة في الدالة الرئيسية ()main:

إذا افترضنا أن هناك شخص وزنه 70 كيلوغراماً وطوله 1.7 متر، نحن نعرف أن هذا الشخص وزنه مناسب، لذا لنختبر البرنامج لنرى إن كان سيعيد النتيجة الصحيحة. سنستدعي دالة ()bmi في دالة ()main ونضع بين قوسيها قيم لمعامليها weight و height من النوع Int، كالتالي:

أنشأنا متغير يمثل الوزن وأسندنا له القيمة 70 كيلوغرام. أما الطول فهو يساوي 1.7 وهو رقم كسري لن تقبله الدالة لأنها تستقبل عدد صحيح من نوع Int. ولا يمكننا إرساله للدالة بالسنتمتر، ﻷن المعادلة داخل الدالة تحتاج الرقم بالمتر. وبما أن المتر يساوي 100 سم، قمنا بتقسيم 170 سم على الرقم 100 سم ونتيجة التقسيم ستكون رقم غير كسري، لذا ستقبل الدالة الرقم. نحفظ النتيجة العائدة من الدالة في متغير status، ثم نطبع قيمته.

ولكن عند طباعة النتيجة، ظهر لنا بأن وزن الشخص زائد Overweight. لماذا؟ لأننا عندما قسمنا 170 على 100، كانت النتيجة 1 متر، على الرغم من أن من المفترض أن تكون النتيجة 1.7. تم حذف الفاصلة وما بعدها لأن هذه هي الطريقة القياسية عند تقسيم العدد الصحيح Int على عدد صحيح آخر في كوتلن وفي البرمجة عمومًا، كما قلنا سابقًا في هذا الدرس.

إذًا ما الحل؟ يمكننا بكل بساطة استخدام نوع بيانات آخر أكثر دقة ويقبل الكسور، مثل النوع Double، والذي تحدثنا عنه في درس أنواع البيانات. لذا سنعدل على معاملات دالة ()bmi، ونجعلها من النوع Double، كالتالي:

ثم نعدل القيم المرسلة في دالة ()main، لتناسب نوع المعاملات الجديد، كالتالي:

لن تقبل الدالة هذه المرة الرقم 70 كقيمة للمعامل weight لأنه في هذه الحالة يعتبر من النوع Int والدالة الآن تحتاج النوع Double، لذا عدلناه وقمنا بإضافة فاصلة والرقم صفر ليصبح 70.0. وأرسلنا الطول بالمتر عادي. وكانت نتيجة الطباعة وزن طبيعي Normal weight. نحن الآن نعرف بأن برنامجنا يعمل بطريقة صحيحة. ليس هذا وحسب، بل يمكننا الآن وضع الوزن والطول بدقة، مثل أن نقول إن وزن الشخص هو 70 كيلوغراماً ونصف، هكذا: 70.5. أو 70 كيلوغراماً وربع: 70.25 …إلخ.

تجاوز سعة العدد الصحيح Integer Overflow:

كما وضحنا في درس أنواع البيانات، عند الإعلان عن متغير من نوع Int، يحجز البرنامج سعة معينة في الذاكرة تتحمل الأعداد في نطاق معين من العدد (231)-  إلى العدد (231) أو من العدد 2147483648- إلى العدد 2147483647. لا يجب أن نتعدى هذا النطاق وإلا ستحدث مشاكل فيما يعرف بمشكلة تجاوز سعة العدد الصحيح Integer Overflow، والتي ستنتج لنا نتيجة غير صحيحة. فمثلًا، إذا كان لدينا الشفرة التالية:

أعلنا عن متغيرين وأسندنا لهما أكبر قيمة لعدد موجب يمكن أن يتحمله النوع Int. ثم جمعنا العددين وأسندنا نتيجة الجمع إلى متغير ثالث، ثم طبعنا النتيجة والتي كانت تساوي بطريقة غريبة 2-. نحن نعرف أن نتيجة جمع العددين أكبر من سالب اثنين، إذًا ما الذي حدث؟

مثل المتغيرين n1 و n2، استنتجت كوتلن أن المتغير الثالث أيضًا من النوع Int على الرغم من أننا أسندنا له قيمة أكبر مما يتحملها الـ Int. وكل ما فعله مترجم كوتلن، هو أنه نبهنا إلى الخطأ بتظليل المتغيرين عند جمعهما باللون الرمادي. وعند وضع مؤشر الفأرة على التظليل في برنامج IntelliJ، ستظهر نافذة تخبرنا بأن هذا سيؤدي إلى مشكلة Integer Overflow، كما في الصورة التالية:

وأيضًا كما نرى في الصورة، لم يوقف المترجم تنفيذ البرنامج ولكن ستكون نتيجة الطباعة خطأ. وبناء على ذلك، نعرف بأن مسؤولية عدم الوقوع في هذا الخطأ، تقع على عاتقنا نحن كمطورين.

استخدام النوع Long:

لتجنب هذا الخطأ، علينا أن نعدل على البرنامج ونضع النوع المناسب للمتغير n3 ليتحمل العدد الكبير الناتج من جمع العددين. كما نعرف من درس أنواع البيانات، أن النوع Long، يمكنه تحمل نطاق عددي من العدد (263)-  إلى العدد (263) أو من العدد 9223372036854775808- إلى العدد 9223372036854775807.

يمكننا بكل بساطة تغيير نوع أحد المتغير n1 و n2 أو كلاهما، إلى النوع Long، بإحدى طريقتين:

  • وضع حرف L بعد الرقم، مثل: val n1 = 2147483647L.
  • ذكر النوع صراحة، مثل: val n1: Long = 2147483647.

أي الطريقتين استخدمنا، سيتم طباعة الرقم الصحيح كنتيجة لجمع العددين وهو العدد: 4294967294 وليس الرقم 2-. كما نرى في الصورة التالية:

وبالطبع أصبح المتغير الثالث n3 نوعه Long تلقائيًا، لأننا أسندنا إليه قيمة جمع متغيرين أحدهما أو كلاهما من النوع Long.

هذا الدرس هو جزء من سلسلة تعليم مبادئ البرمجة بلغة كوتلن. لمُتابعة الدروس منذ البداية ومُشاهدة فهرس المحتويات يمكنك الانتقال إلى الدرس الأول من هنا.

هل أعجبك المحتوى وتريد المزيد منه يصل إلى صندوق بريدك الإلكتروني بشكلٍ دوري؟
انضم إلى قائمة من يقدّرون محتوى إكسڤار واشترك بنشرتنا البريدية.