وزن هامينغ

وزن هامينغ لسلسلة هو عدد الرموز المختلفة عن رمز الصفر في الأبجدية المستخدمة. وهو بالتالي يُعادل مسافة هامينغ من سلسلة جميع رموزها أصفار ولها نفس الطول. في الحالة الأكثر شيوعًا، أي مجموعة معينة من البتات ، يُمثل هذا الوزن عدد البتات التي قيمتها 1، أو مجموع أرقام التمثيل الثنائي لعدد معين ومعيار ℓ₁ لمتجه بت. في هذه الحالة الثنائية، يُطلق عليه أيضًا اسم عدد البتات ، [ 1 ] أو مجموع البتات ، أو المجموع الجانبي ، [ 2 ] أو مجموع البتات . [ 3 ]

أمثلة
خيطوزن هامينغ
111 0 14
111 0 1 0004
000000000
678 0 1234 0 56710
رسم بياني لوزن هامينغ للأعداد من 0 إلى 256 [ 4 ]

التاريخ والاستخدام

سُمّي وزن هامينغ نسبةً إلى عالم الرياضيات الأمريكي ريتشارد هامينغ ، مع أنه لم يكن صاحب الفكرة. [ 5 ] وقد استُخدم وزن هامينغ للأعداد الثنائية عام 1899 من قِبل جيمس دبليو إل غليشر لإعطاء صيغة لعدد معاملات ذات الحدين الفردية في صف واحد من مثلث باسكال . [ 6 ] وقدّم إيرفينغ إس ريد مفهومًا مُكافئًا لوزن هامينغ في الحالة الثنائية عام 1954. [ 7 ]

يُستخدم وزن هامينغ في العديد من المجالات، بما في ذلك نظرية المعلومات ، ونظرية الترميز ، وعلم التشفير . ومن أمثلة تطبيقات وزن هامينغ ما يلي:

التنفيذ الفعال

يُعدّ عدد البتات في سلسلة البتات ضروريًا في علم التشفير وتطبيقات أخرى. ويمكن حساب مسافة هامينغ بين كلمتين A و B من خلال وزن هامينغ لعملية XOR بين A و B. [ 1 ]

لقد حظيت مشكلة كيفية تنفيذها بكفاءة باهتمام واسع في الدراسات. تتوفر عملية حسابية واحدة، أو عمليات متوازية على متجهات البتات، في بعض المعالجات . أما بالنسبة للمعالجات التي تفتقر إلى هذه الميزات، فإن أفضل الحلول المعروفة تعتمد على جمع القيم في نمط شجري. على سبيل المثال، لحساب عدد البتات التي قيمتها 1 في العدد الثنائي ذي 16 بت a  =  0110  1100  1011  1010، يمكن إجراء العمليات التالية:

تعبيرثنائيعشريتعليق
a011011٠٠1011101027834الرقم الأصلي
b0 = (a >> 0) & 01 01 01 01 01 01 01 0101٠٠01٠٠٠٠01٠٠٠٠1، 0، 1، 0، 0، 1، 0، 0كل جزء آخر من
b1 = (a >> 1) & 01 01 01 01 01 01 01 01٠٠0101٠٠010101010، 1، 1، 0، 1، 1، 1، 1الأجزاء المتبقية من
c = b0 + b1010110٠٠011001011، 1، 2، 0، 1، 2، 1، 1عدد الآحاد في كل شريحة ثنائية البت من
d0 = (c >> 0) & 0011 0011 0011 0011٠٠٠١00000010٠٠٠١1، 0، 2، 1كل عدد آخر من ج
d2 = (c >> 2) & 0011 0011 0011 0011٠٠٠١0010٠٠٠١٠٠٠١1، 2، 1، 1العدد المتبقي من ج
e = d0 + d200100010001100102، 2، 3، 2عدد الآحاد في كل شريحة من 4 بتات من
f0 = (e >> 0) & 00001111 0000111100000010000000102، 2كل عدد آخر من هـ
f4 = (e >> 4) & 00001111 0000111100000010000000112، 3العدد المتبقي من هـ
g = f0 + f400000100000001014، 5عدد الآحاد في كل شريحة من 8 بتات من
h0 = (g >> 0) & 000000001111111100000000000001015كل عدد آخر من g
h8 = (g >> 8) & 000000001111111100000000000001004العدد المتبقي من g
i = h0 + h800000000000010019عدد الآحاد في الكلمة الكاملة المكونة من 16 بت

هنا، تُجرى العمليات كما في لغة البرمجة C ، حيث X >> Yتعني `x` إزاحة X إلى اليمين بمقدار Y بت، و`x & Y` تعني عملية AND المنطقية بين X وY، و`+` تعني الجمع العادي. تعتمد أفضل الخوارزميات المعروفة لحل هذه المشكلة على المفهوم الموضح أعلاه، وهي مُدرجة هنا: [ 1 ]

// أنواع البيانات والثوابت المستخدمة في الدوال أدناه // uint64_t هو نوع متغير عدد صحيح غير مُوقّع 64 بت (مُعرّف في إصدار C99 من لغة C) const uint64_t m1 = 0x55555555555555555 ; // ثنائي: 0101... const uint64_t m2 = 0x33333333333333333 ; // ثنائي: 00110011.. const uint64_t m4 = 0x0f0f0f0f0f0f0f0f ; // ثنائي: 4 أصفار، 4 آحاد ... const uint64_t m8 = 0x00ff00ff00ff00ff ; // ثنائي: 8 أصفار، 8 آحاد ... const uint64_t m16 = 0x0000ffff0000ffff ; // ثنائي: 16 صفرًا، 16 آحاد ... const uint64_t m32 = 0x00000000ffffffff ; // ثنائي: 32 صفرًا، 32 آحاد const uint64_t h01 = 0x0101010101010101 ; // مجموع 256 مرفوعًا للأس 0، 1، 2، 3 ...// هذا تطبيق بسيط، معروض للمقارنة، // وللمساعدة في فهم الدوال الأفضل. // تستخدم هذه الخوارزمية 24 عملية حسابية (الإزاحة، والجمع، و AND). int popcount64a ( uint64_t x ) { x = ( x & m1 ) + (( x >> 1 ) & m1 ); // ضع عدد كل 2 بت في هذين البتّين x = ( x & m2 ) + (( x >> 2 ) & m2 ); // ضع عدد كل 4 بت في هذه البتّات الأربعة x = ( x & m4 ) + (( x >> 4 ) & m4 ); // ضع عدد كل 8 بت في هذه البتّات الثمانية x = ( x & m8 ) + (( x >> 8 ) & m8 ); // ضع عدد كل 16 بت في هذه البتّات الستة عشر x = ( x & m16 ) + (( x >> 16 ) & m16 ); // ضع عدد كل 32 بت في تلك الـ 32 بت x = ( x & m32 ) + (( x >> 32 ) & m32 ); // ضع عدد كل 64 بت في تلك الـ 64 بت return x ; }// يستخدم هذا عددًا أقل من العمليات الحسابية مقارنةً بأي تطبيق آخر معروف // على الأجهزة ذات الضرب البطيء. // تستخدم هذه الخوارزمية 17 عملية حسابية. int popcount64b ( uint64_t x ) { x -= ( x >> 1 ) & m1 ; // ضع عدد كل 2 بت في هذين البتّين x = ( x & m2 ) + (( x >> 2 ) & m2 ); // ضع عدد كل 4 بت في هذه البتّات x = ( x + ( x >> 4 )) & m4 ; // ضع عدد كل 8 بت في هذه البتّات x += x >> 8 ; // ضع عدد كل 16 بت في أدنى 8 بتّ x += x >> 16 ; // ضع عدد كل 32 بت في أدنى 8 بتّ x += x >> 32 ; // ضع عدد كل 64 بت في أدنى 8 بتّ return x & 0x7f ; }// يستخدم هذا عددًا أقل من العمليات الحسابية مقارنةً بأي تطبيق آخر معروف // على الأجهزة ذات الضرب السريع. // تستخدم هذه الخوارزمية 12 عملية حسابية، إحداها عملية ضرب. int popcount64c ( uint64_t x ) { x -= ( x >> 1 ) & m1 ; // ضع عدد كل 2 بت في هذين البتّين x = ( x & m2 ) + (( x >> 2 ) & m2 ); // ضع عدد كل 4 بت في هذه البتّات x = ( x + ( x >> 4 )) & m4 ; // ضع عدد كل 8 بت في هذه البتّات return ( x * h01 ) >> 56 ; // تُرجع البتّات الثمانية المتبقية من x + (x<<8) + (x<<16) + (x<<24) + ... }

تتميز التطبيقات المذكورة أعلاه بأفضل أداء في أسوأ الحالات مقارنةً بأي خوارزمية معروفة. مع ذلك، عندما يُتوقع أن تحتوي قيمة ما على عدد قليل من البتات غير الصفرية، قد يكون من الأجدى استخدام خوارزميات تحسب هذه البتات بتًا بتًا. وكما وصف ويغنر في عام 1960 [ 14 فإن عملية AND المنطقية للبتات بين x و x - 1 تختلف عن x فقط في تصفير البت الأقل أهمية غير الصفري: طرح 1 يُحوّل سلسلة الأصفار الموجودة في أقصى اليمين إلى 1، ويُحوّل البت 1 الموجود في أقصى اليمين إلى 0. إذا كانت x تحتوي في الأصل على n بتًا قيمتها 1، فبعد n تكرارًا فقط لهذه العملية، ستُختزل x إلى الصفر. يعتمد التطبيق التالي على هذا المبدأ.  

// يكون هذا أفضل عندما تكون معظم البتات في x تساوي صفرًا. // تعمل هذه الخوارزمية بنفس الطريقة لجميع أحجام البيانات. // تستخدم هذه الخوارزمية 3 عمليات حسابية ومقارنة/تفرع واحد لكل بت "1" في x. int popcount64d ( uint64_t x ) { int count ; for ( count = 0 ; x ; count ++ ) x &= x - 1 ; return count ; }

ومن الأمور الجديرة بالاهتمام هنا العلاقة الوثيقة بين Popcount و FFS و CLZ.

إذا سُمح باستخدام ذاكرة أكبر، يُمكننا حساب وزن هامينغ بشكل أسرع من الطرق المذكورة أعلاه. مع ذاكرة غير محدودة، يُمكننا ببساطة إنشاء جدول بحث كبير لوزن هامينغ لكل عدد صحيح 64 بت. إذا أمكننا تخزين جدول بحث لدالة هامينغ لكل عدد صحيح 16 بت، يُمكننا القيام بما يلي لحساب وزن هامينغ لكل عدد صحيح 32 بت.

static uint8_t wordbits [ 65536 ] = { /* عدد بتات الأعداد الصحيحة من 0 إلى 65535، شاملةً */ }; // تستخدم هذه الخوارزمية 3 عمليات حسابية وقراءتين من الذاكرة. int popcount32e ( uint32_t x ) { return wordbits [ x & 0xFFFF ] + wordbits [ x >> 16 ]; }
// اختياريًا، يمكن ملء جدول wordbits[] باستخدام هذه الدالة int popcount32e_init ( void ) { uint32_t i ; uint16_t x ; int count ; for ( i = 0 ; i <= 0xFFFF ; i ++ ) { x = i ; for ( count = 0 ; x ; count ++ ) // مستعارة من popcount64d() أعلاه x &= x - 1 ; wordbits [ i ] = count ; } }

تم تقديم خوارزمية تكرارية في دونوفان وكيرنيغان [ 15 ]

/* يمكن أن يختلف وزن i عن وزن i / 2 فقط في أقل بت أهمية من i */ int popcount32e_init ( void ) { int i ; for ( i = 1 ; sizeof wordbits / sizeof * wordbits > i ; ++ i ) wordbits [ i ] = wordbits [ i >> 1 ] + ( 1 & i ); }

أظهر Muła et al. [ 16 ] أن النسخة المتجهة من popcount64b يمكن أن تعمل بشكل أسرع من التعليمات المخصصة (على سبيل المثال، popcnt على معالجات x64).

تُعد خوارزمية هارلي-سيل [ 17 ] واحدة من أسرع الخوارزميات التي لا تتطلب سوى عمليات حسابية على الأعداد الصحيحة. [ 18 ]

الحد الأدنى للوزن

في ترميز تصحيح الأخطاء ، يُعرف الحد الأدنى لوزن هامينغ، والذي يُشار إليه عادةً بالوزن الأدنى w<sub> min</sub> للرمز، بأنه وزن أقل كلمة رمزية غير صفرية وزنًا. وزن w لكلمة رمزية هو عدد الآحاد (1) فيها. على سبيل المثال، وزن الكلمة 11001010 هو 4.

في رمز الكتلة الخطي، يمثل الوزن الأدنى أيضًا مسافة هامينغ الدنيا ( d min )، ويحدد قدرة الرمز على تصحيح الأخطاء. إذا كان w min  = n ، فإن d min = وسيصحح الرمز ما يصل إلى d min /2 من الأخطاء. [ 19 ]   

الدعم اللغوي

تُوفّر بعض مُجمّعات لغة C دوالًا مُضمّنة تُتيح إمكانية عدّ البتات. على سبيل المثال، يتضمن مُجمّع GCC (منذ الإصدار 3.4 في أبريل 2004) دالةً مُدمجةً __builtin_popcountتستخدم تعليمة المعالج إن وُجدت، أو تُنفّذها باستخدام مكتبة فعّالة في حال عدم توفّرها. [ 20 ] وقد أضاف مُجمّع LLVM-GCC هذه الدالة منذ الإصدار 1.5 في يونيو 2005. [ 21 ]

في مكتبة C++ القياسيةbitset ، تحتوي بنية بيانات مصفوفة البتات count()على دالة لحساب عدد البتات المُفعّلة. في C++20<bit> ، أُضيف ملف رأس جديد يحتوي على std::popcountدالتين std::has_single_bitتأخذان وسائط من نوع عدد صحيح غير مُوقّع.

BitSetفي لغة جافا، تحتوي بنية بيانات مصفوفة البتات القابلة للتوسيع على BitSet.cardinality()دالة لحساب عدد البتات المُفعّلة. بالإضافة إلى ذلك، توجد Integer.bitCount(int)دالتان Long.bitCount(long)لحساب البتات في الأعداد الصحيحة الأولية ذات 32 بت و64 بت على التوالي. BigIntegerكما تحتوي فئة الأعداد الصحيحة ذات الدقة العشوائية على BigInteger.bitCount()دالة لحساب البتات.

في لغة بايثون ، intيحتوي النوع على bit_count()دالة لحساب عدد البتات المُفعّلة. أُضيفت هذه الخاصية في بايثون 3.10، التي صدرت في أكتوبر 2021. [ 22 ]

في لغة Common Lisp ، تُعيد الدالة logcount، عند إعطائها عددًا صحيحًا غير سالب، عدد البتات التي قيمتها 1. (أما بالنسبة للأعداد الصحيحة السالبة، فتعيد عدد البتات التي قيمتها 0 في تمثيل المتمم الثنائي). في كلتا الحالتين، يمكن أن يكون العدد الصحيح عددًا كبيرًا .

ابتداءً من GHC 7.4، تحتوي حزمة Haskell الأساسية على popCountدالة متاحة لجميع الأنواع التي هي نسخ من Bitsالفئة (المتاحة من Data.Bitsالوحدة النمطية). [ 23 ]

توفر نسخة MySQL من لغة SQLBIT_COUNT() وظيفة قياسية. [ 24 ]

تحتوي لغة فورتران 2008 على الدالة الأساسية القياسية popcntالتي تُرجع عدد البتات غير الصفرية داخل عدد صحيح (أو مصفوفة أعداد صحيحة). [ 25 ]

تحتوي بعض الآلات الحاسبة العلمية القابلة للبرمجة على أوامر خاصة لحساب عدد البتات المُفعّلة، على سبيل المثال #Bفي HP-16C . [ 3 ]

تُنفذ FreePascal دالة popcnt منذ الإصدار 3.0. [ 26 ]

دعم المعالج

انظر أيضاً

مراجع

  1. 1 2 3 4 5 6 7 وارن الابن، هنري س. (2013) [2002]. متعة المخترق (  الطبعة الثانية). أديسون ويسلي - بيرسون للتعليم، الصفحات 81-96 . ISBN  978-0-321-84268-8. 0-321-84268-5.
  2. كنوت، دونالد إرفين (2009). "حيل وتقنيات البتات؛ مخططات القرار الثنائي". فن برمجة الحاسوب . المجلد 4، الجزء 1. أديسون-ويسلي بروفيشنال . ISBN  978-0-321-58050-4.(ملاحظة: مسودة الجزء 1ب مؤرشفة بتاريخ 12-03-2016 على موقع Wayback Machine، وهي متاحة للتنزيل.)
  3. 1 2 دليل مالك جهاز هيوليت-باكارد HP-16C لعالم الحاسوب (ملف PDF) . شركة هيوليت-باكارد . أبريل 1982. 00016-90001. مؤرشف (ملف PDF) من الأصل بتاريخ 28-03-2017 . تم الاطلاع عليه بتاريخ 28-03-2017 .
  4. ر. أوغالدي، لورانس. "إحصاء السكان في لغة برمجة فورمولاي" . فورمولاي . تم الاسترجاع في 2024-06-02 .
  5. تومسون، توماس م. (1983). من رموز تصحيح الأخطاء مروراً بتعبئة الكرات وصولاً إلى الزمر البسيطة . سلسلة كاروس للدراسات الرياضية رقم 21. الجمعية الرياضية الأمريكية . ص 33. 
  6. غليشر، جيمس ويتبريد لي (1899). "حول باقي معامل نظرية ذات الحدين بالنسبة إلى مقياس أولي" . المجلة الفصلية للرياضيات البحتة والتطبيقية . 30 : 150-156 .(ملاحظة: انظر على وجه الخصوص الفقرة الأخيرة من الصفحة  156.)
  7. ريد، إيرفينغ ستوي (1954). "فئة من رموز تصحيح الأخطاء المتعددة ونظام فك التشفير". المجموعة المهنية لنظرية المعلومات التابعة لمعهد مهندسي الراديو (IRE ) . PGIT-4. معهد مهندسي الراديو (IRE): 38-49 .
  8. كوهين، جيرار د .؛ لوبستين، أنطوان؛ ناكاش، ديفيد؛ زيمور، جيل (1998). "كيفية تحسين صندوق أسود لعملية الأسس". في: نيبرغ، كايسا (محرر). التطورات في علم التشفير - يورو كريبت 98، المؤتمر الدولي حول نظرية وتطبيق تقنيات التشفير، إسبو، فنلندا، 31 مايو - 4 يونيو 1998، وقائع المؤتمر . سلسلة محاضرات في علوم الحاسوب. المجلد 1403. سبرينغر. الصفحات 211-220 . doi : 10.1007/BFb0054128 . ISBN   978-3-540-64518-4.
  9. ستويكا، آي.؛ موريس، آر.؛ ليبن-نويل، دي.؛ كارغر، دي آر.؛ كاشوك، إم إف.؛ دابيك، إف.؛ بالاكريشنان، إتش. (فبراير 2003). "Chord: بروتوكول بحث قابل للتوسع من نظير إلى نظير لتطبيقات الإنترنت". معاملات IEEE/ACM في الشبكات . 11 (1): 17-32 . Bibcode : 2003ITNet..11...17S . doi : 10.1109/TNET.2002.808407 . S2CID 221276912. القسم 6.3: "بشكل عام، سيكون عدد الأصابع التي نحتاج إلى تتبعها هو عدد الآحاد في التمثيل الثنائي للمسافة من العقدة إلى الاستعلام. " 
  10. كونغ، أ.و.ك.؛ تشانغ، د.؛ كامل، م.س. (فبراير 2010). "تحليل برنامج IrisCode". مجلة IEEE لمعالجة الصور . 19 (2): 522-532 . Bibcode : 2010ITIP...19..522K . doi : 10.1109/tip.2009.2033427 . PMID: 20083454 . 
  11. هاينز، إي. أ. (سبتمبر 1997). "كيف يلعب دارك ثوت الشطرنج". مجلة ICGA . 20 (3): 166-176 . doi : 10.3233/icg-1997-20304 .تمت مراجعته وإعادة طبعه في كتاب "البحث القابل للتوسع في الشطرنج الحاسوبي" (دار نشر فيوج + توبنر، 2000)، الصفحات 185-198، doi : 10.1007/978-3-322-90178-1_13
  12. 1 2 SPARC International, Inc. (1992). "A.41: تعداد السكان. ملاحظة برمجية". دليل بنية SPARC: الإصدار 9 (الطبعة 9 ). إنجلوود كليفس، نيو جيرسي، الولايات المتحدة الأمريكية: برنتيس هول . ص 205. ISBN   0-13-825001-4.
  13. بلاكسيل، ديفيد (1978). هوغبن، ديفيد؛ فايف، دينيس دبليو (محرران). "ربط السجلات عن طريق مطابقة أنماط البتات" . علوم الحاسوب والإحصاء - الندوة السنوية العاشرة حول الواجهة . منشور خاص من المكتب الوطني للمعايير. 503. وزارة التجارة الأمريكية / المكتب الوطني للمعايير : 146-156 .
  14. فيجنر، بيتر (مايو 1960). "تقنية لحساب الآحاد في الحاسوب الثنائي" . اتصالات رابطة آلات الحوسبة . 3 (5): 322. doi : 10.1145/367236.367286 . S2CID 31683715 . 
  15. دونوفان، آلان؛ كيرنيغان، برايان (2016). لغة البرمجة جو . أديسون-ويسلي. ISBN 978-0-13-419044-0.
  16. مولا، فويتش؛ كورتز، ناثان؛ ليمير، دانيال (يناير 2018). "تعداد أسرع للسكان باستخدام تعليمات AVX2". مجلة الكمبيوتر . 61 (1): 111-120 . arXiv : 1611.07612 . doi : 10.1093/comjnl/bxx046 . S2CID 540973 . 
  17. "Sse-popcount/Popcnt-harley-seal.CPP at master · WojciechMula/Sse-popcount" . GitHub .
  18. مولا، فويتش؛ كورتز، ناثان؛ ليمير، دانيال (2018). "حسابات أسرع للسكان باستخدام تعليمات AVX2". مجلة الكمبيوتر . 61 : 111-120 . arXiv : 1611.07612 . doi : 10.1093/comjnl/bxx046 .
  19. ستيرن ومحمود، تصميم أنظمة الاتصالات ، برنتيس هول ، 2004، ص 477 وما بعدها.
  20. "ملاحظات إصدار GCC 3.4" . مشروع جنو .
  21. "ملاحظات إصدار LLVM 1.5" . مشروع LLVM .
  22. "ما الجديد في بايثون 3.10" . python.org .
  23. "ملاحظات إصدار GHC 7.4.1" .وثائق GHC.
  24. "الفصل 12.11. وظائف البت - دليل مرجعي لـ MySQL 5.0" .
  25. ميتكالف، مايكل؛ ريد، جون؛ كوهين، مالكولم (2011). شرح لغة فورتران الحديثة . مطبعة جامعة أكسفورد . ص 380. ISBN  978-0-19-960142-4.
  26. "وثائق Free Pascal popcnt" . تم الاطلاع عليها بتاريخ 2019-12-07 .
  27. "JDK-6378821: يجب أن تستخدم الدالة bitCount() تقنية POPC على معالجات SPARC و AMD+10h" . قاعدة بيانات أخطاء جافا . 30-01-2006.
  28. مرجع مجموعة تعليمات بلاكفين ( طبعة أولية). شركة أنالوج ديفايسز . 2001. الصفحات 8-24 . رقم القطعة 82-000410-14.  
  29. وولف، كلير (22-03-2019). "امتداد معالجة البتات "B" لـ RISC-V، مسودة الإصدار 0.37" (ملف PDF) . جيت هاب .

للمزيد من القراءة