سؤال

دعنا نقول أن لدي بايت مع ستة قيم غير معروفة:

???1?0??

وأريد مبادلة بت 2 و 4 (بدون تغيير أي من ? القيم):

???0?1??

ولكن كيف سأفعل هذا في عملية واحدة في ج؟

أقوم بإجراء هذه العملية الآلاف من المرات في الثانية الواحدة على ميكروكنترولر حتى الأداء هو الأولوية القصوى.

سيكون على ما يرام "تبديل" هذه البتات. على الرغم من أن هذا ليس هو نفسه تبديل البتات، إلا أن تبديل ستعمل على ما يرام لأغراضي.

هل كانت مفيدة؟

المحلول

محاولة:

x ^= 0x14;

هذا تبديل بت. إنه غير واضح بعض الشيء في السؤال الذي تذكره أولا مبادلة ثم إعطاء مثال تبديل. على أي حال، لمبادلة البتات:

x = precomputed_lookup [x];

حيث يكون Precomputed_lookup مجموعة 256 بايت، يمكن أن يكون أسرع طريقة، فإنه يعتمد على سرعة الذاكرة نسبة إلى سرعة المعالج. خلاف ذلك، إنه:

x = (x & ~0x14) | ((x & 0x10) >> 2) | ((x & 0x04) << 2);

تحرير: بعض المعلومات الأخرى حول تبديل البتات.

عندك XOR (^) القيم عددا صحيحا معا، يتم تنفيذ XOR على مستوى بعض الشيء، مثل هذا:

for each (bit in value 1 and value 2)
   result bit = value 1 bit xor value 2 bit

لذلك هذا القيم الأول من القيمة الأولى هو Xor'ed مع BIT 0 من القيمة الثانية، قليلا 1 مع البتة 1 وما إلى ذلك. لا تؤثر عملية XOR على البتات الأخرى في القيمة. ساري المفعول، إنه XOR قليلا متوازي في العديد من البتات.

بالنظر إلى جدول الحقيقة ل XOR، سترى أن Xor'ing قليلا مع القيمة "1" تبديل بفعالية قليلا.

 a  b a^b
 0  0  0
 0  1  1
 1  0  1
 1  1  0

لذلك، لتبديل BITS 1 و 3، اكتب رقم ثنائي مع واحد حيث تريد قليلا من تبديله وصفر حيث تريد ترك القيمة دون تغيير:

00001010

تحويل إلى عرافة: 0x0a. يمكنك تبديل العديد من البتات كما تريد:

0x39 = 00111001

سوف تبديل بت 0، 3، 4 و 5

نصائح أخرى

لا يمكنك "مبادلة" بت (أماكن تغيير البتات، وليس قيمة) في تعليمات واحدة باستخدام FidDling بت.

الطريقة المثلى إذا كنت ترغب في تبديلها حقا، فربما يكون جدول بحث. هذا ينطبق على العديد من التحولات "المحرجة".

BYTE lookup[256] = {/* left this to your imagination */};

for (/*all my data values */) 
  newValue = lookup[oldValue];

الطريقة التالية ليست تعليمات ج واحدة، إنها مجرد طريقة ثلث بت. كانت الطريقة مبسطة من تبادل البتات الفردية مع XOR.

كما جاء في إجابة رودي, ، سيكون جدول البحث أفضل. أقترح هذا فقط في حال كنت لا ترغب في استخدام واحد. سيؤدي هذا بالفعل إلى تبادل القطع أيضا، وليس فقط تبديل (أي ما هو، كل ما هو في بت 2 سيكون في 4 والعكس صحيح).

  • ب: القيمة الأصلية - ؟؟؟ 1؟ 0 ؟؟ على سبيل المثال
  • X: مجرد درجة حرارة
  • R: النتيجة

    X = ((B >> 2) ^ (b >> 4)) & 0x01
    r = b ^ ((x << 2) | (x << 4))

Explanation السريع: احصل على الجزءين الذي تريد إلقاء نظرة عليه و Xor لهم، تخزين القيمة x. وبعد عن طريق تحويل هذه القيمة إلى البتات 2 و 4 (وأتانة معا) يمكنك الحصول على قناع عند xored مرة أخرى مع b سوف تبديل بت 2 الخاص بك الأصلي. يعرض الجدول أدناه جميع الحالات الممكنة.

bit2: 0 1 0 1  
bit4: 0 0 1 1  
x   : 0 1 1 0   <-- Low bit of x only in this case 
r2  : 0 0 1 1  
r4  : 0 1 0 1

لم اختبر هذا تماما، ولكن بالنسبة للحالات القليلة التي جربتها بسرعة يبدو أنها تعمل.

قد لا يتم تحسين هذا، ولكن يجب أن تعمل:

unsigned char bit_swap(unsigned char n, unsigned char pos1, unsigned char pos2)
{
    unsigned char mask1 = 0x01 << pos1;
    unsigned char mask2 = 0x01 << pos2;
   if ( !((n & mask1) != (n & mask2)) )
        n ^= (mask1 | mask2);
    return n;
}

ستقوم الوظيفة أدناه بتبديل البتات 2 و 4. يمكنك استخدام هذا لتعزيز جدول بحث، إذا لزم الأمر (بحيث يصبح التبديل عملية واحدة):

unsigned char swap24(unsigned char bytein) {
    unsigned char mask2 = ( bytein & 0x04 ) << 2;
    unsigned char mask4 = ( bytein & 0x10 ) >> 2;
    unsigned char mask  = mask2 | mask4 ;
    return ( bytein & 0xeb ) | mask;
}

كتبت كل عملية على خط منفصل لجعله أكثر وضوحا.

قل قيمتك هي X IE، X = ؟؟؟ 1؟ 0 ؟؟

يمكن تبديل الجزءين من هذه العملية:

x = x ^ ((1<<2) | (1<<4));
#include<stdio.h>

void printb(char x) {
    int i;
    for(i =7;i>=0;i--) 
        printf("%d",(1 & (x >> i)));
    printf("\n");
}

int swapb(char c, int p, int q) {
    if( !((c & (1 << p)) >> p) ^ ((c & (1 << q)) >> q) )
        printf("bits are not same will not be swaped\n");
    else {
        c = c ^ (1 << p);
        c = c ^ (1 << q);
    }
    return c;
}

int main() 
{
    char c = 10;
    printb(c);
    c = swapb(c, 3, 1);
    printb(c);
    return 0;
}
void swap_bits(uint32_t& n, int a, int b) {
    bool r = (n & (1 << a)) != 0;
    bool s = (n & (1 << b)) != 0;

    if(r != s) {
        if(r) {
            n |= (1 << b);
            n &= ~(1 << a);
        }
        else {
            n &= ~(1 << b);
            n |= (1 << a);
        }
    }
}

n هو عدد صحيح تريد تبديله، a و b هي المواقف (الفهارس) من البتات التي تريد تبديلها، والعد من القليل أقل أهمية وبدء من الصفر.

باستخدام مثالك (n = ???1?0??)، ستدعو الوظيفة كما يلي:

swap_bits(n, 2, 4);

الأساس المنطقي: تحتاج فقط إلى تبديل البتات إذا كانت مختلفة (لهذا السبب r != s). في هذه الحالة، أحدهم هو 1 والآخر هو 0. بعد ذلك، فقط لاحظ أنك تريد أن تفعل بالضبط مجموعة بت العملية وواحد واضح بعض الشيء عملية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top