0

مُصوِّر أعداد IEEE-754

شاهد بالضبط كيف يُخزّن أي عدد عشري بتنسيق IEEE-754 — بت الإشارة وبتات الأس وبتات الجزء الكسري — ولماذا لا تُخزَّن أعداد مثل 0.1 بشكل دقيق.

🔒 تتم معالجتها بالكامل في متصفحك — ولا يتم تحميل أي شيء تدخله هنا على الإطلاق.

جارٍ المعالجة... 0%
تطبيع العدد
حساب انحياز الأس
توسيع بتات الجزء الكسري
تم

النتيجة

كل عدد فاصلة عائمة يخزنه الحاسوب — سواء كان عدداً في JavaScript أو float في C أو float في Python — يُرمَّز بالطريقة نفسها وفق معيار IEEE 754: بت إشارة واحد، ثم كتلة من بتات الأس، ثم كتلة من بتات الجزء الكسري. الدقة الأحادية (32 بت) تستخدم بت إشارة واحداً و8 بتات للأس و23 بتاً للجزء الكسري؛ أما الدقة المزدوجة (64 بت) — وهي الصيغة التي تقف وراء النوع العددي الافتراضي في معظم لغات البرمجة — فتستخدم بت إشارة واحداً و11 بتاً للأس و52 بتاً للجزء الكسري. تأخذ هذه الأداة أي عدد عشري تكتبه وتُرمِّزه بأي من الدقتين باستخدام مشفر الأعداد العشرية المدمج في المتصفح (DataView/ArrayBuffer) — وهو الآلية نفسها التي يعمل عليها كودك فعلاً — وتُلوِّن كل بت بحسب المنطقة التي ينتمي إليها.

عملية الترميز نفسها تتبع ثلاث خطوات، وهذه الأداة تمر عليها جميعاً بدلاً من مجرد عرض البتات النهائية. أولاً، التطبيع: يُكتب العدد على الصورة 1.جزءكسري × 2^أس، مع وجود رقم واحد فقط غير صفري قبل الفاصلة الثنائية (الأعداد الأصغر من أن تسمح بذلك تُعامَل معاملة الأعداد غير الطبيعية، دون الواحد الضمني). ثانياً، انحياز الأس: بما أن حقل الأس يجب أن يخزن أسساً موجبة وسالبة على شكل عدد غير سالب، يُضاف انحياز ثابت (127 للدقة الأحادية، و1023 للدقة المزدوجة) قبل كتابة الحقل بالنظام الثنائي. ثالثاً، يُوسَّع الجزء الكسري بتاً بتاً بالطريقة التقليدية «اضرب في اثنين، خذ الجزء الصحيح ليكون البت التالي، واحتفظ بالباقي» — ويتكرر هذا حتى يمتلئ حقل الجزء الكسري، وعندها تحدِّد البتات المتبقية ما إذا كانت النتيجة تقرَّب لأعلى أم لأسفل (التقريب إلى أقرب عدد زوجي، وهو الإعداد الافتراضي في IEEE-754).

هذا هو بالضبط سبب عدم تخزين عدد عادي مثل 0.1 بشكل دقيق. ففي النظام الثنائي، 0.1 هو كسر دوري (0.0001100110011… إلى ما لا نهاية)، لذا لا يمكن لأي جزء كسري محدود أن يحتويه بدقة — لا بد من تقريبه في مكان ما. مرِّر 0.1 كمتحول 32 بت واقرأ البتات، فلن تستعيد 0.1، بل ستحصل على 0.100000001490116119384765625 بالضبط. الدقة المزدوجة تملك 29 بتاً إضافياً في الجزء الكسري، لذا خطأ التقريب فيها أصغر بكثير، لكنه ليس صفراً أيضاً — 0.1 كعدد مزدوج دقته 64 بتاً هو بالضبط 0.1000000000000000055511151231257827021181583404541015625. تحسب هذه الأداة تلك القيمة المخزنة الدقيقة باستخدام حساب الأعداد الصحيحة الكبيرة (دون اختصارات الفاصلة العائمة) حتى لا يظل الفرق بين ما كتبته وما يحتفظ به العتاد فعلاً مخفياً أو مقرَّباً أبداً.

تحصل القيم الخاصة على أنماط بتات محجوزة ودقيقة بدلاً من الترميز العادي: الصفر والصفر السالب لهما بتات أس وبتات جزء كسري كلها أصفار (بت الإشارة فقط هو المختلف)، وللانهاية (موجبة أو سالبة) بتات أس كلها وحدات مع بتات جزء كسري كلها أصفار، ولـ NaN بتات أس كلها وحدات مع بت واحد على الأقل في الجزء الكسري. كل شيء هنا يعمل محلياً في متصفحك — لا يُرفع ما تكتبه إلى أي مكان — مما يجعل هذه الأداة مكاناً آمناً لبناء فهم حقيقي لأخطاء الفاصلة العائمة: لماذا `0.1 + 0.2 !== 0.3` في معظم لغات البرمجة تقريباً، ولماذا تخسر أنسجة Float32 في تطبيقات الرسوميات دقة لا تخسرها Float64، ولماذا ينبغي أن تتجنب التطبيقات المالية الفاصلة العائمة الثنائية عموماً.