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

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

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

المنصة

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

الدعم

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

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

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

ليه 0.1 + 0.2 مش بيساوي 0.3؟ حكاية الفاصلة العائمة

مبتدئ21 يوليو 20265 دقائق قراءة
ليه 0.1 + 0.2 مش بيساوي 0.3؟ حكاية الفاصلة العائمة
مستوى المقال: مبتدئ. هنبدأ بمثال بسيط جدًا، وبعدين نرجع نشرح السبب العلمي بالتفصيل والكود. مش محتاج أي رياضيات متقدمة، بس تعرف تجمع كسور.

ليه 0.1 + 0.2 مش بيساوي 0.3؟

افتح أي Python أو Node.js دلوقتي واكتب 0.1 + 0.2. النتيجة اللي هتطلعلك مش 0.3، دي 0.30000000000000004. بعد المقال ده هتعرف بالظبط ليه ده بيحصل، وإزاي تمنعه من إنه يضيّع فلوس عملائك أو يكسر شرط if في كودك.

شفرة ثنائية خضراء من أصفار وواحدات على خلفية سوداء ترمز لتخزين الأرقام العشرية في الحاسوب

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

ركز في السطر ده: تقريبًا كل لغة برمجة بتديك نفس النتيجة الغريبة. جرّبها في JavaScript وJava وC وGo وPHP، كلهم بيقولوا إن 0.1 + 0.2 مش بيساوي 0.3. الناس بتفتكر إن ده باج في اللغة. مش باج. ده سلوك مقصود ومتفق عليه في معيار عالمي اسمه IEEE 754. المشكلة مش في اللغة، المشكلة في إن الكمبيوتر بيخزّن الأرقام بنظام مختلف عن اللي احنا متعوّدين عليه.

الأول بمثال بسيط: ثُلث الكوب

تعالَ نسيب الكمبيوتر شوية. إنت بتكتب الأرقام بالنظام العشري، أساسه 10. جرّب تكتب ثُلث (1/3) بالعشري. هتكتب 0.3333 وتفضل تكتب تلاتات لحد ما تزهق، بس الرقم مبيخلصش أبدًا. لو قرّبته لـ 0.33 وجمعته 3 مرات، هيطلعلك 0.99 مش 1. ضاع منك جزء صغير في التقريب.

الكمبيوتر بيشتغل بالنظام الثنائي، أساسه 2، يعني 0 و1 بس. في النظام ده، الرقم 0.1 بالظبط زي الثُلث عندنا: كسر مالوش نهاية. بيتكتب 0.0001100110011... ويفضل يكرّر لحد ما يخلص المكان المتاح. فالكمبيوتر بيقرّبه ويخزّن أقرب رقم لـ 0.1، مش 0.1 بالظبط. ولمّا تجمع رقمين كل واحد فيهم مقرّب، الأخطاء الصغيرة بتتجمّع وتظهرلك في آخر الرقم.

الشرح العلمي بالتفصيل

دلوقتي بالدقة. النوع اللي بتتخزّن فيه الأرقام العشرية في أغلب اللغات اسمه double يعني دقة مزدوجة بـ 64 بت، حسب معيار IEEE 754. الـ 64 بت دول متقسمين: بت واحد للإشارة، و11 بت للأس (exponent)، و52 بت للجزء الكسري (mantissa). الـ 52 بت دول بيدّوك دقة حوالي 15 إلى 17 رقم عشري معنوي بس، مش أكتر.

عشان كده 0.1 مبيتخزّنش 0.1. بيتخزّن فعليًا الرقم ده: 0.1000000000000000055511151231257827.... الفرق صغير جدًا، حوالي 5.5 في 10 أس -18، بس هو موجود. وبالمثل 0.2 بيتخزّن بفرق بسيط. لمّا تجمعهم، مجموع الفرقين بيطلع كبير كفاية عشان يظهر في الخانة الأخيرة، فتشوف 0.30000000000000004.

السيناريو الواقعي: الفلوس بتضيع

الموضوع ده مش نظري. لو عندك متجر إلكتروني بيبيع منتج بـ 0.10 دولار، وعميل ضاف 1000 قطعة في السلة، وحسبت الإجمالي بـ float بالجمع المتكرر، ممكن يطلعلك 100.00000000000007 بدل 100.00. القيمة دي لوحدها مش كارثة، بس أول ما تقارنها بـ == 100.00 عشان تفعّل خصم أو تطابق فاتورة، الشرط هيفشل من غير سبب واضح. وفي أنظمة محاسبية بتعالج ملايين العمليات في اليوم، الفروق دي بتتراكم وتعمل اختلافات في التقارير المالية بتاخد ساعات عشان تصطاد سببها.

الحل: إزاي تتعامل معاها صح

فيه 3 حلول عملية، كل واحد ليه مكانه:

  1. متقارنش بـ == أبدًا. قارن الفرق بين الرقمين بقيمة صغيرة جدًا (epsilon)، أو استخدم دالة جاهزة زي math.isclose.
  2. للفلوس، استخدم أعداد صحيحة. خزّن السعر بالقرش أو السنت كـ integer بدل ما تخزّنه float.
  3. لو محتاج كسور عشرية دقيقة، استخدم نوع Decimal.
Python
# 1) المقارنة الغلط والصح
print(0.1 + 0.2 == 0.3)                # False

import math
print(math.isclose(0.1 + 0.2, 0.3))    # True

# 2) الفلوس كأعداد صحيحة (بالسنت) — دقة تامة بلا أي خطأ
price_cents = 10                        # 0.10 دولار = 10 سنت
total_cents = price_cents * 1000        # 10000 سنت = 100.00 بالظبط
print(total_cents / 100)               # 100.0

# 3) نوع Decimal للحسابات الحسّاسة
from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2")) # 0.3 بالظبط

المقايضة هنا (trade-off)

مفيش حل ببلاش. الـ float سريع جدًا لأن المعالج بيدعمه في العتاد مباشرة. النوع Decimal بيديك دقة تامة، بس بتكسب الدقة وتخسر السرعة: الحسابات بـ Decimal ممكن تبقى أبطأ بـ 20 إلى 100 مرة من float حسب العملية. فمتستخدمش Decimal في كل حاجة بشكل أعمى. استخدمه في الحتة اللي محتاجة دقة فعلاً، زي الفلوس والفواتير، وسيب float للحسابات اللي فرق 10 أس -16 فيها ملوش أي تأثير.

متى لا تشغل بالك بالموضوع

لو بتشتغل على رسوميات، أو مواقع خرائط، أو حسابات فيزيائية، أو أي حاجة الفرق فيها في الخانة الـ 16 ملوش معنى، سيبك من Decimal وكمّل بـ float عادي. إنك تعقّد كودك بـ Decimal من غير داعي ده over-engineering بيبطّئك ومبيضيفش قيمة. الافتراض إنك محتاج الدقة المطلقة بس لما الأرقام دي بتتحوّل لقرارات: فلوس، أو مطابقة، أو شروط تساوي حرفية.

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

دلوقتي روح على أقرب مكان في كودك بتقارن فيه رقمين عشريين بـ ==، وابدأ بمسار الفلوس تحديدًا. لو لقيت if price == 9.99 أو أي مقارنة float مباشرة، ده أول حاجة تصلّحها: حوّلها لأعداد صحيحة بالقرش، أو استخدم Decimal. وكبداية دلوقتي، اطبع (0.1 + 0.2) - 0.3 في الكود بتاعك، وشوف الرقم الصغير اللي بيطلع بعينك.

مصادر

  • Python Documentation — Floating Point Arithmetic: Issues and Limitations
  • IEEE 754-2019 — IEEE Standard for Floating-Point Arithmetic
  • David Goldberg — What Every Computer Scientist Should Know About Floating-Point Arithmetic (ACM Computing Surveys, 1991)
  • 0.30000000000000004.com — نفس النتيجة في عشرات لغات البرمجة
  • Python Documentation — decimal module

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

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

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