علوم وفضاء

logical_and وbitwise_and: لماذا يختلف ناتجهما؟

ثلاثة أزواج وخرجان مختلفان.
رسم أصلي للأمثلة المسجلة.

نقارن الحقيقة والبتات في مصفوفتين صحيحتين. [1] [2]

حدد معنى العملية

تجري logical_and اختبار الحقيقة عنصرًا بعنصر، بينما تعمل bitwise_and على التمثيل الثنائي للأعداد الصحيحة. ويختصر & العملية البتية على مصفوفات NumPy. [1] [2]

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

الأرقام أمثلة مؤلفة؛ السؤال عن اختلاف المخرجات المسجلة، وعن أثر استعمالها لاختيار المواضع. لا نفترض أن تسمية AND وحدها تحدد معنى كل عدد في الخرج.

سجل القيم والأنواع

في NumPy 2.3.5 على CPython 3.12.14 أنشأنا x=np.array([6,6,0],dtype=np.uint8) وy=np.array([10,9,7],dtype=np.uint8). شكل كل مدخل (3,). لم نستعمل out أو where.

أعاد np.logical_and(x,y) القيم [True,True,False] بنوع bool وشكل (3,). في الموضعين الأول والثاني كلا العددين غير صفري، وفي الثالث يوجد صفر في x.

أعاد np.bitwise_and(x,y) القيم [2,0,0] بنوع uint8 وشكل (3,). ناتج الموضع الثاني صفر؛ لا يدل ذلك هنا على أن أحد المدخلين كان صفرًا، فقد كانا 6 و9.

سجلنا نوع المصفوفة بجانب قيمها في الجدول والصورة. كتابة 2 ليست كتابة True في هذه المقارنة، وخرج البتات المسجل ليس مصفوفة bool.

راجع البتات وتحكم الاختيار

نكتب الأعداد في ثماني خانات: 6 يساوي 00000110، و10 يساوي 00001010. حاصل ضرب رقمي كل خانة يحتفظ بمساهمة وزن 2 فقط؛ مجموع المساهمات يساوي 2.

أما 9 فيكتب 00001001. عند مقارنته مع 00000110 لا نجد خانة واحدة تحمل 1 في الكتابتين معًا؛ مجموع المساهمات صفر. كون 6 و9 غير صفريين لا يغير هذا الحساب الموضعي.

شغّلنا x&y وسجلنا [2,0,0] بنوع uint8 وشكل (3,)، مطابقًا لاستدعاء bitwise_and على المدخلين الصحيحين المختارين.

أنشأنا تحكمًا مختلف المدخلات: x!=0 أعطى [True,True,False]، وy!=0 أعطى [True,True,True]. استدعاء np.bitwise_and(x!=0,y!=0) أعطى [True,True,False] بنوع bool وشكل (3,).

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

استخرجنا المواضع عبر np.flatnonzero: من الخرج المنطقي حصلنا على [0,1]؛ ومن مقارنة الخرج البتي بعدم الصفر حصلنا على [0]. الفهارس تبدأ من الصفر، والموضع الثاني في المثال هو الفهرس 1.

الاختياران إذن مختلفان في هذا المثال. لم نختبر تطبيق ترشيح بعينه، ولا ندعي أن أحد الاختيارين يناسب كل غرض.

خانات ثنائية ومساهماتها المشتركة.
رسم أصلي للأمثلة المسجلة.

وسع الفحص ضمن نطاق معلوم

أخذنا جميع الأزواج a,b من 0 إلى 31 شاملًا الطرفين؛ العدد 32×32=1024 زوجًا. لكل زوج أنشأنا مدخلين uint8، كل منهما مصفوفة بعنصر واحد.

مرجع البتات مستقل: لكل k من 0 إلى 7 نحسب (a//2**k)%2 ونظيره للعدد b؛ نضرب الرقمين في 2**k ثم نجمع المساهمات الثماني. لا يستخدم المرجع عاملًا بتيًا في Python أو دوال NumPy البتية والمنطقية.

مرجع الحقيقة هو ((a!=0)*(b!=0))==1. ناتج كل مقارنة قيمة منطقية؛ حاصل ضربهما هنا إما صفر أو واحد. هذا مرجع مستقل للأزواج الصحيحة المختارة.

لكل زوج خمسة فحوص: قيمة الخرج المنطقي ونوعه وشكله؛ وقيمة الخرج البتي ونوعه وشكله؛ ومطابقة x&y؛ والتحكم البولياني الصريح؛ وثبات بايتات المدخلين. تشمل المطابقتان أيضًا النوع والشكل.

أضفنا ستة تحكمات للمثال الثلاثي: الخرجان، و&، والتحكم البولياني، وقائمتا الفهارس، وثبات بايتات المدخلين. الإجمالي 1024×5+6=5126، ومرت جميع الفحوص.

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

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

x / uint8y / uint8logical_and / boolbitwise_and / uint8
610True2
69True0
07False0

للتوسع: الجمع والطرح في النظام الثنائي.

المراجع

  1. NumPy 2.3 — logical_and
  2. NumPy 2.3 — bitwise_and

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