2015-11-04 5 views
8

Was wäre eine schnelle und elegante Möglichkeit, die ersten (am wenigsten signifikanten) 2 verschiedene aufeinanderfolgende Bits in einer vorzeichenlosen Ganzzahl zu tauschen?Wie tausche ich zuerst 2 aufeinanderfolgende verschiedene Bits

z.

100100 -> 100010 
110011 -> 110101 

Bisher kam ich mit auf den Punkt:

unsigned long long special_swap(unsigned long long number) 
{ 
    if (number & 1) 
     return (number + 1)^((number^(number + 1)) >> 2); 
    number = ~number; 
    return ~((number + 1)^((number^(number + 1)) >> 2)); 
} 

Meine größte Unzufriedenheit mit der obigen Lösung ist, dass sie die if Befehl verwendet.

+0

Was ist zuerst? Am weitesten links? Ganz rechts? – sehe

+2

Interessant: https://graphics.stanford.edu/~seander/bithacks.html#SwappingBitsXOR – sehe

+1

Erstellen Sie eine Hash-Tabelle aller 256 möglichen Zustände, in denen ein Byte enthalten sein kann, und die gewünschte Transformation. Dann mach einfach den Blick nach oben. Wiederholen Sie den Vorgang für das nächste Byte, falls erforderlich. –

Antwort

4

Dies ist, wie ich es tun würde:

unsigned long long my_swap(unsigned long long number) 
{ 
unsigned long long x = number^(number >> 1); 
return number^((x & -x) * 3); 
} 

Meine Lösung gibt 0 zurück, wenn die Anzahl == 0, während die Funktion der ursprünglichen Frage zurück 1100000000000000000000000000000000000000000000000000000000000000.

Einige Erklärungen: Die Bits von x enthalten 0, wenn das Bit an dieser Position gleich dem nächsten Bit ist, und 1, wenn es anders ist. (x & -x) ist das niedrigstwertige Bit von x, das heißt die erste Bitdifferenz.

+0

Ich betrachtete die Funktion in 0 undefiniert, also ist das in Ordnung. Wie bist du auf x^(x >> 1) gekommen, was bringt das? – kaspersky

+0

Ich habe meine Antwort bearbeitet. –

+1

Hinweis: Diese Funktion hat auch einen Fall, der nicht wie erwartet behandelt wird: Wenn alle Bits 1 sind, setzt sie das höchste Bit auf 0. Die Funktion der Frage (und meine Version davon) setzt jedoch die zwei höchsten Bits zu 0. Wie auch immer: das ist eine sehr schöne Lösung! – alain

3

Dies ist die gleiche Idee ohne eine if zu verwenden.

unsigned long long special_swap(unsigned long long number) 
{ 
    unsigned long long t = ((number & 1) << 1) - 1; 
    return (number + t)^((number^(number + t)) >> 2); 
} 

Die Variablen t entweder 1 oder -1, abhängig von der lsb der Nummer.

Test it live

Verwandte Themen