Solución:
Analicemos esto.
return ( ((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1) );
Primero, veremos (x & 0xaaaaaaaa)
. Si te rompes 0xaaaaaaaa
hasta el nivel de bits, terminas con 1010 1010 1010 1010 1010 1010 1010 1010
(como a
, en binario, es 1010
). Entonces (x & 0xaaaaaaaa)
está diciendo, devuelva solo todos los lugares pares 1
en x
. Esto se llama enmascaramiento de bits. Luego, lo desplaza a la derecha un lugar; así es como hace que los números pares cambien de lugar (por lo que ahora el segundo bit ocupa el lugar del primer bit, y el cuarto el tercero, etc.).
Haces lo mismo con (x & 0x55555555)
– si lo desglosas al nivel de bits, terminas con 0101 0101 0101 0101 0101 0101 0101 0101
(como 5
, en binario, es 0101
). Esto enmascara todas las partes pares en x
, y te da todos los bits extraños. Luego, desplaza todos los bits a la izquierda en 1. Finalmente, usa el or
(|
) para combinar las dos secuencias de bits, y esa es su respuesta.
Ejemplo: tomemos 2456086205. Convertimos eso en binario y obtenemos 1001 0010 0110 0100 1110 0110 1011 1101
. Ahora lo hacemos (x & 0xaaaaaaaa)
, y obten
1001 0010 0110 0100 1110 0110 1011 1101 & 1010 1010 1010 1010 1010 1010 1010 1010
,
que es igual 1000 0010 0010 0000 1010 0010 1010 1000
. Cambie esto a la derecha y obtendrá 0100 0001 0001 0000 0101 0001 0101 0100
.
Ahora haz (x & 0x55555555)
, y obten
1001 0010 0110 0100 1110 0110 1011 1101 & 0101 0101 0101 0101 0101 0101 0101 0101
,
que es igual 0001 0000 0100 0100 0100 0100 0001 0101
. Cambie esto a la izquierda y obtendrá 0010 0000 1000 1000 1000 1000 0010 1010
.
Finalmente lo hacemos 0100 0001 0001 0000 0101 0001 0101 0100 | 0010 0000 1000 1000 1000 1000 0010 1010
. Entonces obtenemos 0110 0001 1001 1000 1101 1001 0111 1110
, que, como puede ver, ¡es la solución!
Convirtiendo a binario,
0xaaaaaaaa == 0b10101010101010101010101010101010
0x55555555 == 0b01010101010101010101010101010101
Estos números tienen 0 y 1 configurados en ubicaciones alternas, por lo que cuando &
un número con uno de estos, selecciona cada segundo bit.
Si realiza el procedimiento swapOddEvenBits con un número entero, digamos 0b01111100111101001111110000110010
, obtenemos
0xaaaaaaaa & 0b01111100111101001111110000110010 selects the following bits:
0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1 # unselected bits are 0
0x55555555 & 0b01111100111101001111110000110010 selects the following bits:
1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 0
0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1 gets shifted right:
0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1
and
1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 0 gets shifted left:
1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 0
and we | the results back together:
0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1
1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 0
-------------------------------
10111100111110001111110000110001