علوم وفضاء

hypot: حين يفشل التربيع المباشر

مدخلان ومساران.
قيم hypot مقربة للعرض.

نقارن hypot بالتربيع والجمع والجذر المباشر. [1]

اقرأ الصيغة وحدد السؤال

تعرف الوثائق hypot بحساب وتر المثلث، وتعرض المكافئ الرياضي sqrt(x**2+y**2) عنصرًا بعنصر. [1]

سؤالنا عن تنفيذ هذه الصيغة في float64: هل تعطي مضاعفة كل مدخل في نفسه، ثم الجمع والجذر، النتيجة نفسها التي يعطيها استدعاء hypot؟ الصيغة الرياضية لا تسجل وحدها المراحل الوسيطة للبرنامج.

الأعداد تعليمية بلا وحدة مادية؛ لا تمثل أبعاد جسم أو حدود جهاز قياس. نستخدم المدخلات نفسها في المسارين ونحفظ القيم والأنواع، دون وصف خوارزمية hypot الداخلية.

احفظ مخرجات hypot

في NumPy 2.3.5 على CPython 3.12.14 أنشأنا x=np.array([5e200,5,5e-200],dtype=np.float64) وy=np.array([12e200,12,12e-200],dtype=np.float64). لكل مصفوفة ثلاثة عناصر؛ لم نحدد out أو where.

شغّلنا h=np.hypot(x,y). سجلنا [1.3000000000000002e201,13.0,1.3e-199]، بنوع float64 وشكل (3,). كانت العناصر الثلاثة محدودة وموجبة في هذا المثال.

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

حفظنا بايتات x وy قبل الاستدعاءات وبعدها؛ لم تتغير. هذا تحقق من مدخلاتنا، ولا يثبت مشاركة ذاكرة بين المدخلات والمخرجات أو سلوك خيارات إخراج لم نجربها.

تتبع التربيع والجمع والجذر

شغّلنا xx=x*x وyy=y*y، ثم sums=xx+yy، ثم direct=np.sqrt(sums). سجلنا xx بالقيم [+inf,25,0] وyy بالقيم [+inf,144,0]؛ المجموع [+inf,169,0] والجذر [+inf,13,0]. كل مرحلة float64 بالشكل (3,).

استعملنا لهذا المسار np.errstate(over='ignore',under='ignore') محليًا. سياق errstate يضبط معالجة الأخطاء أثناءه ثم يعيد الإعداد السابق عند الخروج. [2] لم نفحص سياسة التحذير الافتراضية، ولم نستخدم هذا الإعداد لتغيير المدخلات.

في الموضع الكبير ظهرت +inf في المربعين قبل الجمع والجذر، رغم أن x وy كانا عددين محدودين. وفي الموضع الصغير صار المربعان صفرًا قبل الجمع، رغم أن المدخلين كانا موجبين وغير صفريين.

عند معامل حقيقي مثالي موجب s، يعطي (5s)**2+(12s)**2=(25+144)*s**2=169*s**2، والجذر الموجب 13s. إذا أخذنا s=1e200 فالناتج المثالي 1.3e201؛ وإذا أخذنا s=1e−200 فهو 1.3e−199، وكلاهما موجب في الحساب الرياضي.

هذه مراجعة رياضية، لا وصف لتخزين كل عدد عشري في float64 بدقة. مرجع التشغيل اللاحق يبدأ من القيم الثنائية التي وصلت فعلًا إلى المصفوفة، فلا يفترض أن العدد المكتوب في الشيفرة حُفظ عشريًا دون تقريب.

في الموضع الأوسط تحقق 25+144=169 ثم الجذر 13، واتفق المساران. وفي الطرفين بقي h محدودًا بينما انتهى المسار المباشر إلى +inf أو صفر. لا نعمم ذلك على كل نوع أو حجم، ولا نستنتج طريقة التنفيذ الداخلية من النتائج.

مراحل المسار المباشر.
مخرجات مسجلة.

راجع المرجع وحدود الفحص

أخذنا a وb من 1 إلى 8، ومع كل زوج ثلاث قيم للمعامل s: 1e200 و1 و1e−200. المدخلان a*s وb*s في مصفوفتين float64 بعنصر واحد. عدد الحالات 8×8×3=192؛ المثال الثلاثي 5 و12 مراجعة إضافية خارج هذه الشبكة.

حوّلنا كل مدخل عائم فعلي بواسطة Decimal.from_float، ثم حسبنا الجذر العشري لمجموع مربعيه بدقة 100 رقم. لا يستدعي المرجع sqrt أو hypot في NumPy أو math.hypot؛ إنه مرجع عشري محدود الدقة، وليس مساواة دقيقة لكل جذر غير نسبي.

حسبنا الخطأ النسبي بين قيمة hypot العائمة بعد تحويلها إلى Decimal وبين المرجع، وقسمناه على المرجع الموجب. حددنا سماحًا 1e−15؛ أكبر خطأ مسجل في شبكة الحالات كان نحو 1.49e−16.

لكل حالة ثلاثة فحوص: قيمة hypot مقارنة بالمرجع مع النوع والشكل والمحدودية؛ والمسار المباشر مع نوعه وشكله وتصنيف +inf أو الصفر في المعاملين الكبير والصغير، أو مقارنة المرجع عند s=1؛ وثبات بايتات المدخلين.

أضفنا ستة تحكمات للمثال الثلاثي: hypot والمرجع؛ والجذر المباشر؛ والمربعان؛ والمجموع؛ وأنواع المراحل وأشكالها؛ وثبات الأصلين. الإجمالي 192×3+6=582، ومرت جميع الفحوص.

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

بقاء الناتج محدودًا في الحالات المختارة لا يمنح ضمان دقة عامًا. صف النتيجة مع النوع والإصدار والمدخلات والمرجع والسماح؛ لا تحول اختبارًا محدود النطاق إلى وعد باستقرار كل حساب.

x / float64y / float64hypot / float64direct sqrt / float64
5e20012e2001.3000000000000002e201+inf
5121313
5e−20012e−2001.3e−1990

للتوسع: برهان فيثاغورس بالمساحات.

المراجع

  1. NumPy 2.3 — hypot
  2. NumPy 2.3 — errstate

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