مع الأنواع i1 وu1 وf2، أعطى تجميع الأولين قبل الثالث float32، وأعطى تجميع الأخيرين قبل الأول float16. نكتب الخطوتين الوسيطتين كي نرى ما غيرته الأقواس، دون جمع قيم عددية.
الزوج والتجميع
تعيد promote_types وصف نوع؛ وتماثل الزوج لا يضمن ثبات التجميع. [1]
نسمي الدالة p في كتابة المسار لتقصير العرض. نقارن p(p(a,b),c) مع p(a,p(b,c)). ظلت a وb وc في مواضعها في المقارنة الواحدة؛ لم نبدل الثالث بالأول عندما نقلنا الأقواس.
هناك سؤال آخر هو مبادلة طرفي نداء واحد. ذلك ليس السؤال الذي يجيب عنه الجدول هنا؛ فالجدول يحفظ ناتجًا وسيطًا، ثم يدخله في نداء ثانٍ. لا يكفي تشابه أسماء المدخلات الثلاثة كي نهمل هذه الخطوة.
شغّلنا NumPy 2.3.5 وCPython 3.12.14. المدخلات أوصاف أنواع عددية مكتوبة كنصوص، وكل مخرج كائن dtype؛ الاسم الذي نعرضه خاصية فيه، وليس قيمة عائمة رجعت من جمع أعداد.
اخترنا ثلاث مجموعات أصلية: (i1,u1,f2) و(i2,u2,f4) و(i1,u1,f4). لا نستعمل مثال النصوص الحرفية في صفحة التوثيق، ولا نتعامل مع بنية حقول أو ترتيب بايتات غير أصلي.
خطوتان محفوظتان
في الصف الأول، a="i1" وb="u1" وc="f2". رجع p(a,b) كائن int16 من الفئة i وبحجم عنصر 2 بايت. ثم مررنا الكائن نفسه مع c إلى p، فرجع float32 من الفئة f وبحجم عنصر 4 بايتات.
في التجميع الآخر، بدأنا p(b,c). رجع float16 من الفئة f وبحجم عنصر 2 بايت. ثم مررناه مع a إلى p، فرجع float16 أيضًا. حفظنا الناتج الوسيط، ولم نستبدله بنص الاسم لكي ننشئ وصفًا جديدًا في الخطوة الثانية.
إذن تساوت قائمة المدخلات الأصلية، لكن اختلف النوع الوسيط: int16 في مسار وfloat16 في الآخر. بعدها اختلف الاسمان النهائيان float32 وfloat16. يحدد السجل أي زوج دخل أولًا، فلا نعرض اختلاف الاسم بلا سبب قابل للفحص.
الاسمان النهائيان يصفان حجم عنصر 4 و2 بايت في هذا التشغيل. لا نعد ذلك قياسًا لتوفير ذاكرة برنامج أو لحجم كائن Python، ولا نتيجة عن سرعة أحد المسارين. لم نخصص مصفوفتين لقياس حجم بياناتهما.
وكتابة f2 ضمن القائمة لا تعني أن التجميعين انتهيا إليها؛ لقد ظهر float32 في المسار الأول. نحتفظ بالمخرج المسجل بدل اختيار اسم من المدخلات لأنه يبدو مناسبًا للخلاصة.
مثال وتحكم
في مجموعة (i2,u2,f4)، أعطى p(i2,u2) الوصف int32، ثم ضمه إلى f4 أعطى float64. وأعطى p(u2,f4) الوصف float32، ثم ضمه إلى i2 أبقى float32. هذان الاسمان النهائيان مختلفان أيضًا.
أضفنا التحكم (i1,u1,f4)؛ لم نغير النوعين الصحيحين في المثال الأول، لكن بدلنا النوع العائم المدخل من f2 إلى f4. بقي الناتج الوسيط الأول int16، ثم أعطى ضمه إلى f4 الوصف float32.
وفي مسار التحكم الآخر رجع p(u1,f4) بالوصف float32، ثم أعطى ضمه إلى i1 الوصف float32. وافق الاسمان النهائيان بعضهما، مع اختلاف النوع الوسيط بين int16 وfloat32.
تساوي الناتج في التحكم لا يمحو اختلافه في المثالين السابقين. وكذلك اختلاف مثال واحد لا يثبت أن كل ثلاثية ستختلف؛ نحتاج المدخلات الفعلية ومساري التنفيذ حتى نحدد الحكم على الصف المقصود.
لم ننشئ عناصر عائمة لاختبار خطأ تقريب، ولم نقس ضياع قيمة كبيرة أو صغيرة. الفرق هنا في أوصاف الأنواع المعادة. لذلك لا نضيف إلى الشكل نسبة خطأ أو رقمًا قال السجل إنه خرج من عملية حساب لم ننفذها.

حصر النداءات
أخذنا الترتيبات الستة لكل مجموعة من الأنواع الثلاثة، فصارت 3×6=18 ثلاثية مرتبة. كل صف يثبت ترتيب a وb وc ثم يغير الأقواس فقط؛ تبديل ترتيب العناصر يحدث بين الصفوف، وليس داخل المقارنة الواحدة.
لكل صف نداءان في المسار الأول ونداءان في الثاني؛ المجموع 18×4=72 نداء promote_types. عاد 72 وصفًا من dtype دون سجل خطأ. الأوصاف الوسيطة داخلة في العدد، وليست نداءات مخفية نضيفها مرة أخرى.
حفظنا name وkind وitemsize واسم فئة الكائن لكل عودة. هذه حقول مرافقة للكائن الواحد؛ لا نسميها 288 مخرجًا مستقلًا. لا توجد قيم عددية أصلية أو عناصر مصفوفة رجعت من الدالة في هذا الاختبار.
اختلف الاسمان النهائيان في ثمانية صفوف، واتفقا في عشرة؛ 8+10=18. هذه حصيلة الصفوف المعلنة، وليست احتمال اختلاف نوع في أي برنامج أو عينة عشوائية من كل الأنواع.
كتبنا مرجع الأزواج في Python قبل تشغيل النداءات، ثم توقعنا الوصفين الوسيطين والنهائيين لكل ترتيب. لم يستدعِ المرجع promote_types أو دالة NumPy أخرى لصنع التوقعات. وافقت الأسماء والفئات وأحجام العناصر التوقعات المحفوظة.
اقتصر الاختبار على هذه الأنواع والأوصاف والإصدار. لم ننفذ جمع قيم أو تحويل بيانات أو result_type أو can_cast، ولم نختبر أنواعًا مركبة أو نصية أو زمنية أو مخصصة أو بنى حقول أو ترتيب بايتات أو أداءً أو إصدارات أخرى. احفظ التجميع والنوع الوسيط حين تراجع سلسلة من ثلاثة أوصاف.
| a / b / c | p(p(a,b),c) | p(a,p(b,c)) |
|---|---|---|
| i1 / u1 / f2 | float32 | float16 |
| i2 / u2 / f4 | float64 | float32 |
| i1 / u1 / f4 | float32 | float32 |
للتوسع: حدود التجميع.
المراجع
أُعدّ هذا المقال بمساعدة الذكاء الاصطناعي، وخضع لمراجعة ذاتية بالأداة نفسها. لا يُنسب إلى مراجع بشري أو خبير مستقل. منهجية المحتوى.
