أوبس!! هل حقا ما أراه؟
موضوعنا اليوم سيكون مختلفا قليلا عن المواضيع التي طرحتها سابقا فلن أتحدث عن إنشاء مكون أو أداة برمجية أو عن مشروع معين حديثي اليوم سيكون بعض الأمور التي ليس من المتوقع ان تحدث عند كتابة اي برنامج لكنها تحدث و قد يتعجب بعض المبرمجين من سبب حدوثها.
في الحالة الأولى أنظر معي للشيفرة التالية:
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 تتعامل مع الارقام و تجعلها تقوم بالعمليات الحسابية بطريقة خاصة و تحتفظ بقيمة تقريبية للناتج
للتأكد من هذا الكلام قم بتجربة الشيفرة التالية:
{
Console.WriteLine(i);
}
سيكون الناتج كما في الصورة أدناه:
أمر مدهش أليس كذلك
لو بحثت عن القيمة 0.6 التي كنا نستخدمها في عبارة if من أجل المقارنة فلن تجدها
اذن فالمتحول i لن يحتوي على القيمة 0.6 في أي حال من الاحوال
ما هو الحل لهذه المشكلة ؟ حسنا كما اخبرتكم سابقا بسبب الطبيعة الخاصة للتعامل مع الاعداد ذات الفاصلة العائمة فسيتم تخزين قيمة تقريبية للعدد و ليس العدد نفسه لذا يمكن ان نعتبر ان المتحول i وصل للقيمة 0.6 عندما تكون قيمته قريبة جدا منها
لذا سنتستخدم الشيفرة التالية و التي ستعمل بشكل صحيح معنا:
{
if ((i > 0.59f)&&(i < 0.6f))
{
Console.WriteLine(“0.6”);
}
}
نلتقي في الجزء الثاني مع حالة مدهشة جديدة
ُEmail : TammamKoujan@Gmail.com
يجوز نشر هذه المقالة أو أجزاء منها بشرط المحافظة على اسم الكاتب و ذكر المصدر
Comments on: "أوبس!! هل حقا ما أراه؟" (4)
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.
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
شرح رائع
على الرغم من قوة اللغة إلا أنه يوجد الكثير من الثغرات مثل التي ذكرت على العموم أنا جربت الكود على لغة البرمجة delphi و لكن بما أن حلقة For ترفض القيم ذات الفاصلة العشرية قمت بتجربتها على حلقة While والنتيجة كانت سليمة مع لغة delphi و حتى مع الإصدارات القديمة من هذه اللغة أقصد Turbo pascal كانت النتيجة سليمة
تحياتي لك
وسام محمود