0

IEEE-754 المتخيل العائم

تعرف بالضبط على كيفية تخزين الرقم العشري كرقم عائم IEEE-754 - بت الإشارة، وبتات الأس، وبتات الجزء العشري - ولماذا لا يتم تخزين أرقام مثل 0.1 بالضبط.

Buy Me a Coffee at ko-fi.com
جارٍ المعالجة... 0%
التطبيع
حساب التحيز الأسي
توسيع بتات العشري
تم

النتيجة

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

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

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

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