أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالمناهج والباقات
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

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

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
البرمجة بالعربي

ليه 0.1 + 0.2 مش بيساوي 0.3؟ الفاصلة العائمة للمبتدئين

مبتدئ٣٠ يونيو ٢٠٢٦4 دقائق قراءة
ليه 0.1 + 0.2 مش بيساوي 0.3؟ الفاصلة العائمة للمبتدئين

هذا المقال يتطلب مستوى: مبتدئ. لو لسه بادئ في البرمجة وصدمك إن الكمبيوتر "بيغلط" في جمع كسرين بسيطين، المقال ده ليك.

افتح أي محرر بايثون دلوقتي واكتب 0.1 + 0.2. الناتج اللي هيطلعلك مش 0.3، ده 0.30000000000000004. نفس الحاجة بتحصل في جافاسكريبت و C و Java وكل لغة تقريبًا. ده مش باج في اللغة، وده مش عطل في جهازك. ده سلوك مقصود اسمه الفاصلة العائمة (Floating Point). في آخر المقال هتعرف ليه بيحصل، وإزاي تتعامل معاه في كودك من غير ما يفسدلك حسابات الفلوس.

الفاصلة العائمة: ليه الكمبيوتر بيقرّب الكسور

المشكلة باختصار

الكمبيوتر بيخزّن الأرقام بنظام ثنائي (أصفار وواحدات بس). بعض الكسور البسيطة عندنا في النظام العشري مالهاش تمثيل دقيق ومنتهي في النظام الثنائي. فالجهاز بيقرّبها لأقرب قيمة يقدر يخزنها. التقريب الصغير ده هو اللي بيظهر في صورة ذيل غريب زي ...00004 لما تجمع رقمين.

الفكرة بمثال قبل الكلام العلمي

تخيّل إنك بتقسم رغيف على 3 أشخاص بالتساوي. كل واحد ياخد ثلث. لو حبيت تكتب الثلث بالأرقام العشرية هتكتب 0.3333... والتلاتات دي مش بتخلص أبدًا. لو وقفت عند 4 خانات (0.3333) يبقى انت قرّبت، والناتج "قريب جدًا" من الثلث بس مش بالظبط هو.

الكمبيوتر بيواجه نفس المشكلة بالظبط، بس مع الرقم 0.1. الرقم ده سهل علينا في النظام العشري، لكن في النظام الثنائي بيتكتب 0.000110011001... وبيفضل بيكرّر بلا نهاية، زي التلاتات بتاعتنا. فالجهاز بيقف عند حد معين ويقرّب. لما تجمع تقريبين مع بعض، الناتج بيبان فيه فرق بسيط جدًا.

مقارنة بين كسر عشري 1 على 3 يساوي 0.3333 لا ينتهي وكسر ثنائي 0.1 يساوي 0.00011001 لا ينتهي مما يفسر التقريب

الشرح العلمي الدقيق

الأرقام الكسرية في معظم اللغات بتتخزن حسب معيار اسمه IEEE 754 بصيغة "double" بطول 64 بت. الـ 64 بت دول متقسمين على 3 أجزاء: بت واحد للإشارة (موجب/سالب)، 11 بت للأس (يحدد مكان الفاصلة)، و52 بت بس لتخزين أرقام الرقم نفسه (المانتيسا).

مخطط تنسيق IEEE-754 مزدوج الدقة 64 بت موزعة على بت إشارة و11 بت أس و52 بت مانتيسا للأرقام المخزنة

الـ 52 بت دول بيدوك دقة حوالي 15 إلى 17 خانة عشرية معنوية. أي رقم محتاج أطول من كده بيتقرّب. عشان كده 0.1 المخزّن فعليًا مش 0.1 بالظبط، هو رقم أقرب ليه بفرق ضئيل جدًا في حدود 5.5e-17. لما تجمع 0.1 المقرّب مع 0.2 المقرّب، الفرقين بيتجمعوا ويظهروا في الناتج.

الكود: شوف المشكلة والحل بنفسك

Python
# شغّل ده في بايثون وشوف بنفسك
a = 0.1 + 0.2
print(a)            # 0.30000000000000004
print(a == 0.3)     # False  <-- الفخ اللي بيوقّع المبتدئين

# الحل 1: متقارنش بالمساواة المباشرة، قارن بالتقريب
import math
print(math.isclose(a, 0.3))   # True

# الحل 2: لو بتشتغل بفلوس، استخدم Decimal
from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2"))   # 0.3 بالظبط

ركز في حاجة مهمة: Decimal("0.1") مكتوبة كنص بين علامتي تنصيص، مش Decimal(0.1). لو كتبتها رقم عادي هتورّث نفس مشكلة التقريب، فخليها دايمًا نص.

سيناريو واقعي بيحصل فعلاً

لو عندك سلة شراء فيها 1000 منتج وبتجمع أسعارهم بـ float، الفروق الضئيلة دي بتتراكم. ممكن المجموع يطلع 4999.9999999998 بدل 5000.00، أو يفرق قرش في الفاتورة. القرش ده لوحده مش مشكلة، لكن في نظام محاسبي بيعالج آلاف العمليات يوميًا، الفروق دي بتكبر وبتعمل اختلاف بين رصيد الحسابات. عشان كده البنوك والأنظمة المالية بتبعد عن float في الفلوس.

الـ trade-off اللي لازم تعرفه

الحل بـ Decimal دقيق في الكسور العشرية، بس له ثمن. هو أبطأ من float بفرق ملموس (في حدود 10 لـ 100 مرة حسب العملية)، وبياخد ذاكرة أكتر. الافتراض هنا إنك بتتعامل مع فلوس أو قيم لازم تكون مظبوطة بالقرش؛ في الحالة دي الدقة أهم من السرعة. لكن لو بتعمل رسوميات أو حسابات فيزيائية على ملايين النقاط، السرعة بتفرق جدًا وfloat بيكون الاختيار الصح رغم التقريب.

متى لا تستخدم هذه الطريقة

متستخدمش Decimal في كل حاجة لمجرد إنه "أدق". في حسابات علمية أو رسم أو ذكاء اصطناعي أو أي شغل فيه ملايين العمليات في الثانية، الـ Decimal هيبطّئك من غير فايدة حقيقية، لأن فرق التقريب الضئيل مش مؤثر هناك أصلًا. وكمان متقارنش رقمين float بـ == أبدًا، حتى لو مش بتشتغل بفلوس؛ استخدم math.isclose.

الخطوة التالية

دوّر في كودك على أي مقارنة == بين رقمين عشريين واستبدلها بـ math.isclose. وأي مكان بتحسب فيه فلوس بـ float حوّله لـ Decimal مع كتابة القيم كنصوص. جرّب الكود اللي فوق دلوقتي وشوف الناتج بعينك؛ ده أسرع طريقة تثبّت الفكرة في دماغك.

المصادر

  • توثيق بايثون الرسمي: Floating Point Arithmetic: Issues and Limitations — docs.python.org/3/tutorial/floatingpoint.html
  • معيار IEEE 754-2019 للأرقام ذات الفاصلة العائمة (IEEE Standard for Floating-Point Arithmetic)
  • David Goldberg — "What Every Computer Scientist Should Know About Floating-Point Arithmetic"، مجلة ACM Computing Surveys
  • توثيق بايثون لوحدة decimal و الدالة math.isclose (PEP 485)
  • الموقع التوضيحي 0.30000000000000004.com اللي بيوضح نفس السلوك عبر اللغات المختلفة

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة