تمثيل الفاصلة العائمة
تشكّل الأعداد الحقيقية سلسلة متصلة لا نهاية لها، بينما ذاكرة الحاسوب محدودة. يمثّل معيار IEEE 754 مزدوج الدقة (القياسي في NumPy وMATLAB وJulia وكل برامج الحسابات العلمية) كل عدد غير صفري بالشكل:
نظرًا لأن الجزء الكسري يحوي عددًا محدودًا من البتات، لا يمكن تمثيل معظم الأعداد الحقيقية بدقة — بل تُقرَّب إلى أقرب عدد ذي فاصلة عائمة. الكمية الأساسية التي تقيس هذه الدقة هي إبسيلون الآلة ε_mach: أصغر عدد موجب بحيث 1 + ε_mach ≠ 1 في حساب الفاصلة العائمة. في الدقة المزدوجة، ε_mach = 2⁻⁵² ≈ 2.2 × 10⁻¹⁶.
يُحدد إبسيلون الآلة خطأ التقريب النسبي في عملية واحدة من عمليات الفاصلة العائمة. لأي عدد حقيقي x، يحقق تمثيله fl(x) الشرط: |fl(x) − x| / |x| ≤ ε_mach. وهذا الحد مشدود لا فضفاض: الأعداد من الشكل 1 + δ حيث δ ≈ ε_mach/2 تُقرَّب إلى 1.0 بالضبط. ومجموعة الأعداد المزدوجة القابلة للتمثيل فيها فجوات تكبر مع كبر المقدار: الفجوة بين العدد العشري المزدوج 10¹⁵ والتالي له تقدر بـ 10¹⁵ · ε_mach ≈ 0.2، فلا يمكن التمييز بين 10¹⁵ و10¹⁵ + 0.1 في الدقة المزدوجة.
الإلغاء الكارثي
أخطر مصادر أخطاء الفاصلة العائمة هو الإلغاء الكارثي: طرح عددين متقاربين جدًا. إذا كان a = 1.000000000000001 وb = 1.000000000000000 (كلاهما مخزن بـ16 رقمًا)، فإن a − b = 1×10⁻¹⁵ لا يحمل سوى رقم واحد معنوي — أُتلفت خمسة عشر خانة من الدقة في عملية طرح واحدة. والخطأ النسبي في الناتج قد يكون هائلًا رغم أن أيًّا من المدخلين لم يحمل خطأً على الإطلاق. المثال الكلاسيكي هو الصيغة التربيعية: عندما يقترب المميّز b² − 4ac من الصفر يكون الطرح المباشر كارثة عددية، والبديل المستقر يستخدم العلاقة x₁x₂ = c/a لحساب الجذر الأصغر بعد إيجاد الأكبر بدقة.
وهذه قاعدة عملية تنفعك: إذا حسبت a − b وكان |a − b| ≪ |a|، فقد خسرت نحو log₁₀(|a|/|a−b|) خانة عشرية من الدقة. وإعادة هيكلة الحساب لتجنّب مثل هذا الطرح — كاستخدام log1p(x) بدلًا من حساب log(1+x) بسذاجة عند x الصغيرة، أو استخدام جمع كاهان في المجاميع الطويلة — ممارسة قياسية في البرمجيات العددية.
رقم التكييف
لنفترض المنظومة الخطية Ax = b. إذا تعرض الطرف الأيمن b لاضطراب صغير δb، تؤدي المنظومة المضطربة A(x + δx) = b + δb إلى δx = A⁻¹δb. التغير النسبي في الحل مقارنةً بالتغير النسبي في البيانات محدود بما يلي:
رقم التكييف κ(A) لا يعتمد على b؛ إنه خاصية للمصفوفة A وحدها. بشكل حدسي، يقيس مدى "انبساط" المصفوفة: المصفوفة جيدة التكييف تُحوّل الكرة إلى شكل شبه كروي؛ أما سيئة التكييف فتُحوّلها إلى قطع ناقص مستطيل الشكل جدًا، وتساوي نسبة أطول محور إلى أقصرها رقم التكييف κ(A). حين تقترب σ_min من الصفر، يتجه κ(A) إلى اللانهاية — أي أن المصفوفة تكاد تُسقط اتجاهًا بأكمله إلى الصفر، وأي ضوضاء في ذلك الاتجاه في b تُضخَّم بشكل هائل في x.
والتحليل نفسه ينطبق على الاضطرابات في A ذاتها. فلو حللنا (A + δA)x̃ = b، كان الخطأ النسبي في x̃ مقارنةً بالحل الحقيقي محدودًا بما يقارب κ(A) · ‖δA‖/‖A‖. وفي حساب الفاصلة العائمة تُقرَّب A نفسها عند تخزينها، فيكون δA من رتبة ε_mach · ‖A‖. وهكذا يربط رقم التكييف بين الخطأ الارتجاعي — حجم الاضطراب اللازم ليصبح الجواب المحسوب دقيقًا — والخطأ الأمامي، أي الخطأ الفعلي في الجواب: الخطأ الأمامي ≲ κ(A) × الخطأ الارتجاعي.
حساب رقم التكييف
في NumPy/MATLAB، تحسب الدالة cond(A) قيمة κ₂(A) = σ_max/σ_min عبر SVD. وهذا يكلف O(mn min(m,n)) لمصفوفة m×n — وهو ثمن باهظ إن كان كل ما تريده تشخيص المنظومة. والتقدير الأرخص هو مقلوب رقم التكييف عبر rcond(A)، الذي يستخدم تقديرًا تجريبيًا بتكلفة O(n²) مبنيًا على تحليل LU. كقاعدة عملية: إذا كان κ(A) ≈ 10^k، تفقد نحو k خانة عشرية من الدقة مقارنةً بما كان الحساب قادرًا على منحه. في الدقة المزدوجة (16 خانة)، رقم تكييف يساوي 10¹² لا يترك سوى ~4 خانات صحيحة في الحل — وهذا سوء غير مقبول في كثير من التطبيقات.
المسائل جيدة وسيئة التكييف
المسألة جيدة التكييف هي التي تُفضي فيها التغيرات الصغيرة في المدخلات إلى تغيرات صغيرة في المخرجات: κ(A) صغير. المسألة سيئة التكييف تملك κ(A) ≫ 1 — اضطراب بسيط في البيانات قد يُحدث تغيرًا ضخمًا في الحل. وسوء التكييف خاصية للمسألة الرياضية نفسها، لا للخوارزمية التي تحلّها. فالخوارزمية المستقرة إذا طُبّقت على مسألة سيئة التكييف أعادت جوابًا سيئًا كذلك — كل ما تضمنه أنها لن تزيد الأمر سوءًا فوق ما يفرضه التكييف.
المثال الكلاسيكي هو مصفوفة هيلبرت: Hᵢⱼ = 1/(i+j−1). رقم تكييف مصفوفة هيلبرت 10×10 هو κ₂(H₁₀) ≈ 1.6×10¹³ — حل المنظومة H₁₀x = b بالدقة المزدوجة يعطي على الأكثر 16 − 13 = 3 خانات صحيحة في x مهما كانت الخوارزمية المستخدمة. وتظهر مصفوفة هيلبرت طبيعيًا في انحدار متعددات الحدود: حين تلائم متعددة حدود من الدرجة n−1 على n نقطة متساوية التباعد بالأساس الأحادي، تحصل عليها بالضبط. ولهذا انحدار متعددات الحدود عالية الدرجة خطر عدديًا.
مصادر سوء التكييف في التطبيق
تظهر منظومات خطية سيئة التكييف في كل مكان في الرياضيات التطبيقية:
- ميزات متعددة الخطية: في الانحدار، إذا كانت عمودان من مصفوفة التصميم X متوازيين تقريبًا (ميزتان مرتبطتان ارتباطًا شديدًا)، تمتلك XᵀX قيمة ذاتية صغيرة جدًا ويكبر رقم تكييفها. وتنظيم ريدج (إضافة λI) يرفع جميع القيم الذاتية بمقدار λ، فيحدّ رقم التكييف عند (σ_max² + λ)/λ.
- ملاءمة متعدد الحدود بالأساس الأحادي: مصفوفة فاندرموند Vᵢⱼ = xᵢʲ⁻¹ سيئة التكييف جدًا للدرجات العالية والعقد المتقاربة. الانتقال إلى قاعدة متعاملة (ليجاندر، تشيبيشيف) يقلل رقم التكييف بشكل كبير.
- معادلات تفاضلية منفصلة: تُنتج تقنيات الفروق المنتهية أو العناصر المنتهية مصفوفات رقم تكييفها يتناسب مع O(1/h²) حيث h فاصل الشبكة. والتهيئة المسبقة — الضرب في معكوس تقريبي — ضرورية لتتقارب الحلّالات التكرارية أصلًا.
- منظومات شبه شاذة: إذا كان النظام الفيزيائي قريبًا من الرنين أو من التشعب أو شبه منحلّ — كدائرتين لهما ترددان متساويان تقريبًا — صارت المصفوفة الحاكمة له شبه شاذة وحساسة عدديًا.
الاستقرار العددي للخوارزميات
خوارزميتان تحلان المسألة نفسها رياضيًا قد تتصرفان بطريقتين مختلفتين عدديًا. خوارزمية مستقرة عدديًا تُعيد نتيجةً هي الإجابة الدقيقة لمسألة مضطربة قليلًا (خطأ ارتجاعي صغير). خوارزمية غير مستقرة قد تُدخل أخطاءً أكبر بكثير مما يقتضيه رقم التكييف — أي تضخّم أخطاء التقريب بلا داعٍ.
التخلص الغاوسي بدون محورية غير مستقر: مواجهة محور صغير تقسّمه يُضخّم أخطاء التقريب تضخيمًا انفجاريًا. المحورية الجزئية — استخدام أكبر عنصر في العمود الحالي محورًا دائمًا — تمنع ذلك وتجعل تحليل LU مستقرًا ارتجاعيًا من الناحية العملية. وعلى المنوال نفسه: حساب A⁻¹ صراحةً ثم تكوين A⁻¹b لحل Ax = b تصرّف مُهدِر (O(n³) للمعكوس مقابل O(n³/3) لتحليل LU) وأقل استقرارًا من الحل المباشر عبر LU أو QR.
نهج تحليل QR لمسائل المربعات الصغرى (حل Rw = Qᵀy بدلًا من تكوين XᵀX) مثال رئيسي لتحسين الاستقرار. المعادلات الطبيعية XᵀXw = Xᵀy تُربّع رقم التكييف: κ(XᵀX) = κ(X)². إذا كان κ(X) = 10⁸، فإن κ(XᵀX) = 10¹⁶ — شبه شاذ في الدقة المزدوجة. نهج QR يعمل مباشرةً على X ورقم تكييفه κ(X) = 10⁸، يمنح 8 خانات صحيحة بينما تُعطي المعادلات الطبيعية صفرًا. لهذا تستخدم كل البرامج الجادة (scipy.linalg.lstsq وNumPy lstsq ودالة lm() في R) تحليل QR أو SVD داخليًا، ولا تستخدم المعادلات الطبيعية مباشرةً.
متى تقلق بشأن الدقة العددية
قائمة مراجعة عملية للموثوقية العددية:
- تحقق من رقم التكييف أولًا: إذا كان κ(A) > 10^(16/p) حيث p هو عدد الخانات المطلوبة، لن تحقق دقة p خانة في الدقة المزدوجة.
- تجنب تكوين AᵀA صراحةً لمسائل المربعات الصغرى؛ استخدم QR أو SVD مباشرةً.
- لا تعكس المصفوفة لحل منظومة خطية؛ استخدم صيغة مُحلَّلة (LU، QR، Cholesky) وحلّ بالإحلال.
- نظّم بياناتك في الانحدار: تنظيم أعمدة X يقرّب قيمه الشاذة من بعضها ويقلل κ(XᵀX).
- استخدم التنظيم (حافز/تيخونوف) حين تكون المسألة سيئة التكييف في جوهرها؛ معامل التنظيم λ يحدّ رقم التكييف الفعلي.
- راقب البواقي: بعد حساب x̃، احسب ‖Ax̃ − b‖/‖b‖. البقية الصغيرة تعني الخطأ الارتجاعي صغير؛ الخطأ الأمامي الكبير رغم البقية الصغيرة يعني أن المسألة سيئة التكييف.
في NumPy: np.finfo(float).eps تعطي ε_mach ≈ 2.2e-16. np.linalg.cond(A) تحسب κ₂(A). np.linalg.solve(A,b) تستخدم LU مع محورية جزئية (مستقرة ارتجاعيًا). np.linalg.lstsq(A,b) تستخدم SVD وتضع عتبة للقيم الشاذة الصغيرة. وفي MATLAB، يختار مُعامل الشرطة المقلوبة (\) تحليل LU أو QR تلقائيًا حسب بنية المصفوفة. حين تبدو نتائج منظومتك صحيحة خوارزميًا لكنها خاطئة، احسب رقم التكييف أولًا — الإجابة كثيرًا ما تكمن في حساسية المسألة الرياضية ذاتها لا في خطأ في الكود.
إبسيلون الآلة ε_mach ≈ 2.2×10⁻¹⁶ يحدد خطأ التقريب النسبي في عملية واحدة. الإلغاء الكارثي (طرح عددين متقاربين) يمحو خانات كثيرة دفعةً واحدة. رقم التكييف κ(A) = σ_max/σ_min يحدد كم خانة تُفقد: ‖δx‖/‖x‖ ≤ κ(A) ‖δb‖/‖b‖. رقم تكييف يساوي 10^k يكلّف k خانة عشرية من الدقة. سوء التكييف خاصية رياضية؛ الخوارزمية المستقرة لا تستطيع تجاوز حد رقم التكييف لكن الخوارزمية غير المستقرة تُفاقمه. احلّ دائمًا Ax = b عبر تحليل، ولا تعكس المصفوفة؛ ولمسائل المربعات الصغرى استخدم QR أو SVD لتجنب تربيع رقم التكييف.