أهلا بكم في عالمي


أوبس!! هل حقا ما أراه؟

بسم الله الرحمن الرحيم

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

for (float i = 0.5f; i < 1; i += 0.01f)
{
if (i == 0.6f)
{
Console.WriteLine(i);
}
}

في مقطع الشيفرة السابق أنشأت حلقة for و عرفت فيها المتحول i من النوع float و مهدته بالقيمة 0.5 و جعلت مقدار الزيادة على المتحول i في كل مرة تساوي 0.01 اي واحد بالمئة و جعلت الحلقة مستمرة طالما المتحول i اصغر من القيمة 1
حسنا كل شيء حتى الان طبيعي و صحيح
وضعت ضمن كتلة الحلقة عبارة if تقوم بطباعة قيمة المتحول i على الشاشة عندما تبلغ هذه القيمة 0.6
تبعا للشرح المنطقي السابق ستتوقع ان كل شيء صحيح و انه نتيجة تنفيذ مقطع الشيفرة السابق ستكون طباعة قيمة المتحول i عندما يصبح 0.6
اسف لان اخيب املك و اقول لك بأن شيئا لن يحدث و لن تطبع قيمة المتحول i ابدا
و للتأكد من هذا الامر قم بنسخ الشيفرة السابقة و ضعها في مشروع جديد و قم بالتنفيذ .
بعد أن تأكدنا من هذاالكلام دعنا نفسر ما الذي حدث و كيف نتجاوز هذه المشكلة
تكمن المشكلة السابقة في تعريفنا للمتحول i على انه من النوع float و الأنواع الخاصة بالفاصلة العائمة مثل float تتعامل مع الارقام و تجعلها تقوم بالعمليات الحسابية بطريقة خاصة و تحتفظ بقيمة تقريبية للناتج
للتأكد من هذا الكلام قم بتجربة الشيفرة التالية:

for (float i = 0.5f; i < 1; i += 0.01f)
{
Console.WriteLine(i);
}

سيكون الناتج كما في الصورة أدناه:

cmd.jpg

أمر مدهش أليس كذلك
لو بحثت عن القيمة 0.6 التي كنا نستخدمها في عبارة if من أجل المقارنة فلن تجدها
اذن فالمتحول i لن يحتوي على القيمة 0.6 في أي حال من الاحوال
ما هو الحل لهذه المشكلة ؟ حسنا كما اخبرتكم سابقا بسبب الطبيعة الخاصة للتعامل مع الاعداد ذات الفاصلة العائمة فسيتم تخزين قيمة تقريبية للعدد و ليس العدد نفسه لذا يمكن ان نعتبر ان المتحول i وصل للقيمة 0.6 عندما تكون قيمته قريبة جدا منها
لذا سنتستخدم الشيفرة التالية و التي ستعمل بشكل صحيح معنا:

for (float i = 0.5f; i < 1; i += 0.01f)
{
if ((i > 0.59f)&&(i < 0.6f))
{
Console.WriteLine(“0.6”);
}
}

نلتقي في الجزء الثاني مع حالة مدهشة جديدة

تمام كوجان في 29/07/2007
ُEmail : TammamKoujan@Gmail.com
يجوز نشر هذه المقالة أو أجزاء منها بشرط المحافظة على اسم الكاتب و ذكر المصدر

Comments on: "أوبس!! هل حقا ما أراه؟" (4)

  1. Sorry for my English comment, I can’t read arabic.

    I can only guess what this post is about from the pictures and the code, but might like to read one of my posts on floating point numbers and one of JRM’s.

  2. you are right i am talking about the float point numbers and the .NET framework
    realy it is a series of articles talking about unusual or unexpected things may face the developers.
    thank you for your useful comment and the URL for your nice article

  3. تجارة العملات said:

    شرح رائع

  4. على الرغم من قوة اللغة إلا أنه يوجد الكثير من الثغرات مثل التي ذكرت على العموم أنا جربت الكود على لغة البرمجة delphi و لكن بما أن حلقة For ترفض القيم ذات الفاصلة العشرية قمت بتجربتها على حلقة While والنتيجة كانت سليمة مع لغة delphi و حتى مع الإصدارات القديمة من هذه اللغة أقصد Turbo pascal كانت النتيجة سليمة
    تحياتي لك
    وسام محمود

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: