اشتباهات رایج در استفاده از ایونت‌های کانستراکت 2

توقّع دقیق بودن محاسبات ریاضی

تمام کامپیوترهای مدرن اعداد اعشاری را در قالبی مثل 0.5 نگهداری می‌کنند. چون حافظه و قدرت پردازش کامپیوتر بی‌نهایت نیست، کامپیوتر مجبور می‌شود کمی اعداد را گرد کند. این به نوبه‌ی خود می‌تواند باعث شود جوابی که کامپیوتر به دست می‌آورد کمی دور از جواب حقیقی باشد، مثلاً در جایی که توقّع دارید کامپیوتر به شما عدد 1 را نشان دهد عدد 0.999999 را نمایش می‌دهد.

حالا توضیح می‌دهیم این مشکل چرا پیش می‌آید. تقسیم عدد 1 بر 3 را در نظر بگیرید. جواب می‌شود 0.3333333… که همین طور تا ابد 3 تکرار می‌شود. امّا کامپیوتر حافظه‌ی محدودی دارد و نمی‌تواند بی‌نهایت عدد مثل این بی‌نهایت 3 را در حافظه‌اش نگه دارد. بنابراین فقط تعداد محدودی از اعشار را ذخیره می‌کند و بعد از آن، محاسبه را متوقّف می‌کند. مثلاً فقط تا 6 رقم اعشار را نگه می‌دارد و جواب می‌شود 0.333333 . این از لحاظ ریاضی غلط است، ولی کامپیوتر نمی‌تواند جواب درست را نگه دارد. حالا فرض کنید این جواب را مجدداً در 3 ضرب کنیم. شما انتظار دارید سه ضرب‌در یک‌سوّم برابر 1 شود، ولی در حقیقت عدد 0.999999 را دریافت می‌کنید که خیلی به جواب اصلی نزدیک است، ولی دقیق نیست. اگر بازی شما بخواهد که جواب دقیقاً مساوی 1 شود، آنگونه که انتظار دارید عمل نمی‌کند. معمولاً می‌توانید از طریق دیباگر (debugger) جوابی را که واقعاً محاسبه می‌شود بررسی کنید.

این نوع مشکل در محاسبات اعشاری در اغلب نرم‌افزارها وجود دارد. راه فراری نیست! این حقیقت نحوه‌ی عملکرد کامپیوترهاست. مثال ما در بالا در مبنای 10 بود، درحالی‌که کامپیوتر در مبنای 2 کار می‌کند، و دوره‌ی گردش رقم‌های اعشار در مبنای 2 با مبنای 10 فرق می‌کند. یعنی 0.1 در مبنای 10 یک عدد اعشاری مختوم است و دوره‌ی گردش ندارد، ولی همین عدد وقتی به مبنای 2 می‌رود دارای دوره‌ی گردش می‌شود. یعنی این مشکل حتّی در مواقعی که انتظارش را هم ندارید می‌تواند اتّفاق بیفتد، حتّی اگر فکر کنید که دارید با اعداد دقیقی محسابه می‌کنید. این مشکل مخصوصاً در محلّ اشیاء اثر می‌گذارد، چون حرکت یک شیء در زاویه‌ای خاص معمولاً نیاز به محاسبات سینوس و کسینوسی دارد، که معمولاً جواب بسیار نزدیکی به جواب اصلی به دست می‌آید، ولی دقیق نیست.

راهکاری که می‌توانید از آن در هر نرم‌افزار و فریم‌ورکی برای حلّ این مشکل استفاده کنید این است که مقداری تلرانس[1] را مجاز اعلام کنید. توقّع نداشته‌باشید ایونتی مثل Sprite.X = 100 همیشه درست کار کند. به جای آن از چیزی مثل [2]abs(Sprite.X – 100) < 0.01 استفاده کنید. این کار مقایسه‌ی شما را درست می‌کند، زیرا اگر نتیجه تا 0.1 از 100 فاصله داشت، باز هم ایونت اجرا می‌شود. پس اگر مثلاً عدد ما 99.999999 شد باز هم همان طور که انتظار داریم، ایونت اجرا می‌شود.

[1] تلرانس: به خطای مجاز تلرانس گفته می‌شود، مثلاً می‌گوییم اگر جواب به دست آمده تا 0.2 با جواب اصلی فرق داشت عیبی ندارد (در این حالت تلرانس ما 0.2 است).

[2] طبق اصول ریاضی، قدر مطلق تفاضل دو عدد، فاصله‌ی آن دو از هم را نشان می‌دهد. پس در این‌جا گفته‌ایم اگر فاصله‌ی بین Sprite.X و 100 کمتر از 0.01 باشد اکشن‌ها را اجرا کن (در این مثال تلرانس 0.01 است)

سؤالات فنی خود را فقط در انجمن بپرسید. در غیر این صورت پاسخ داده نخواهد شد.
۴ نظر

افزودن دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

تمامی حقوق برای مرجع تخصصی کانستراکت محفوظ است.