تحدد وثائق ldexp أسسًا صحيحة لحساب الضرب بقوة اثنين. [1] نختبر القيم نفسها داخل int32 وfloat64.
افصل القيمة عن نوع المدخل
المعامل الأول يدخل في الضرب بقوة اثنين؛ المعامل الثاني محدد في الوثائق كأُس صحيح. [1]
سؤال تجربتنا ضيق: هل يكفي أن نقرأ 3.0 ونقول إن قيمته تساوي ثلاثة، أم يجب أيضًا الانتباه إلى نوع المصفوفة التي تحمله؟ نكتب القيمة والنوع في خانتين منفصلتين قبل التشغيل.
لا نقارن هنا طريقة حساب الأعداد الثنائية يدويًا، ولا نفكك عددًا بواسطة frexp. نؤلف معاملًا وأسًا لكل موضع، ثم نرى ما يقبله الاستدعاء وما يعيده في البيئة المعلنة.
احسب المثال المقبول
أنشأنا x=np.array([1.75,-2.5,0.375],dtype=np.float64)، وe=np.array([-2,3,4],dtype=np.int32). شكل كل منهما (3,). استخدمنا np.ldexp(x,e) دون out أو where أو اختيار dtype للناتج.
ظهر الناتج بالقيم 0.4375 و−20.0 و6.0، ونوعه float64 وشكله (3,). في هذا المثال لم نجرب إدخال معاملات صحيحة أو نوعًا عائمًا آخر؛ لا نستنتج قاعدة عامة لنوع الناتج من حالة واحدة.
التغير ليس جمعًا للأس مع المعامل. معاملنا 1.75 اقترن بالأس −2، فأعطى 0.4375؛ معامل −2.5 اقترن بالأس 3 فأعطى −20، ومعامل 0.375 اقترن بالأس 4 فأعطى 6.
حفظ التشغيل البايتات الأصلية لكل من x وe قبل الاستدعاء وبعده، ووجدها متساوية. هذا فحص لعدم تغيير مدخلينا، ولا يختبر مشاركة الذاكرة أو خيارات الإخراج التي لم نستخدمها.
راجع الحساب ثم غيّر النوع
قبل الاعتماد على الخرج، حسبنا مرجعًا مستقلًا باستخدام fractions.Fraction. للموضع الأول نكتب 1.75=7/4 و2**−2=1/4؛ حاصل الضرب 7/16، أي 0.4375.
للموضع الثاني نكتب −2.5=−5/2، ونضربه في 8 فنحصل على −20. وللثالث نكتب 0.375=3/8، ونضربه في 16 فنحصل على 6. الأعداد المختارة ممثلة بدقة في float64 ضمن هذه التجربة.
بعد ذلك أنشأنا ef=e.astype(np.float64). بقيت القيم المقروءة −2.0 و3.0 و4.0 مساوية عدديًا لأسسنا السابقة، لكن نوع ef أصبح float64. عند np.ldexp(x,ef) ظهر TypeError في NumPy 2.3.5.
وشغّلنا تحكمًا آخر بأسس float64 قيمها −2.0 و3.5 و4.0؛ ظهر TypeError أيضًا. لم يحاول هذا التحكم أن يحدد سياسة مناسبة لتحويل 3.5 إلى عدد صحيح، ولم نخف الخطأ باقتطاع الكسر.
إذن قبول أسس int32 ورفض النسخة float64 ذات القيم المتساوية حالتان موثقتان في تشغيلنا. عند مراجعة خطأ مماثل نحتفظ بنوع المدخل ضمن سجل التجربة؛ مقارنة القيم وحدها لا تعيد وصف الاستدعاء الذي جربناه.

حدد ما تثبته الشبكة
وسعنا المثال إلى معاملات k/8، حيث k صحيح من −16 إلى 16؛ عددها 33. قابلنا كل معامل بأسس int32 من −6 إلى 6، وعددها 13. استخدمنا مصفوفتين من عنصر واحد وبالشكل نفسه في كل حالة.
عدد الحالات 33×13=429. لكل حالة حسبنا Fraction(k,8)×Fraction(2)**n، ثم حولنا الكسر المرجعي إلى float. هذه القيم الصغيرة المختارة قابلة للتمثيل الدقيق؛ المرجع لا يستدعي ldexp أو frexp أو math.ldexp أو أسس NumPy.
راجعنا في كل حالة خمسة أشياء: مساواة القيمة للمرجع، ونوع الناتج وشكله معًا، وثبات بايتات المعامل، وثبات بايتات الأس، وظهور TypeError عند استبدال مصفوفة الأس بنسخة float64.
إجمالي الشبكة 429×5=2145 فحصًا. أضفنا ستة تحكمات للمثال الثلاثي: قيم الناتج، ونوعه وشكله، وثبات كل من المدخلين، ورفض نسختي الأسس العائمتين. صار الإجمالي 2151 ومرت جميع الفحوص.
لا يشمل النطاق تغير النوع بين إصدارات المكتبة، ولا أنواعًا أخرى أو مدخلات مركبة أو اختلاف الأشكال أو out وwhere، ولا الفائض أو الاضمحلال العددي أو إشارة الصفر أو الذاكرة والأداء. الأرقام تعليمية مؤلفة وليست نتائج قياس أو وصفًا لحل مهمة فعلية.
| المعاملات | الأسس | نوع الأسس | نتيجة التشغيل |
|---|---|---|---|
| 1.75؛ −2.5؛ 0.375 | −2؛ 3؛ 4 | int32 | 0.4375؛ −20؛ 6 / float64 |
| نفس المعاملات | −2.0؛ 3.0؛ 4.0 | float64 | TypeError |
| نفس المعاملات | −2.0؛ 3.5؛ 4.0 | float64 | TypeError |
للتوسع: الحساب الثنائي.
المراجع
أُعدّ هذا المقال بمساعدة الذكاء الاصطناعي، وخضع لمراجعة ذاتية بالأداة نفسها. لا يُنسب إلى مراجع بشري أو خبير مستقل. منهجية المحتوى.
