Un problema interesante que he estado reflexionando sobre los últimos días es cómo copiar los bits de un entero en otro número entero en una posición dada en el número entero de destino. Entonces, por ejemplo, dado el entero de destino 0xdeadbeef
y el entero de origen 0xabcd
, la idea sería obtener un resultado de 0xabcdbeef
(dada una posición de destino de 16 bits) o 0xdeabcdef
(dada una posición de destino de 8 bits).Algoritmo para la copia de N bits en la posición arbitraria de uno a otro int
Con la limitación arbitraria de evitar condicionales o bucles (permitiendo a mí mismo para usar Simplemente operaciones matemáticas/bit a bit), he desarrollado la siguiente función (C++)
int setbits(int destination, int source, int at, int numbits)
{
int ones = ((1<<(numbits))-1)<<at;
return (ones|destination)^((~source<<at)&ones);
}
donde at
es el lugar donde los bits de fuente debe ser copiado en el número de destino (0-31) y numbits
es el número de bits que se copia desde source
(1-32). Por lo que puedo decir, este algoritmo funciona para todos los valores excepto at
= 0 y numbits
= 32 (el caso en el que el entero de origen se sobreescribe entero) debido al hecho de que 1 < < 32 resultados en 1 (ya que el cambio se envuelve alrededor) en oposición a 0.
Mis preguntas son:
- cómo es esto normalmente hecho? ¿Hay algún algoritmo particularmente notable utilizado (por notable, estoy preguntando si hay trucos particularmente eficientes que se pueden utilizar para hacer esto)?
- funciona mi algoritmo, así como creo que no (es decir, funciona para todos los valores excepto a = 0 y numbits = 32)?
- relacionados a 1), ¿hay alguna manera de hacer esto sólo con operadores matemáticos/bit a bit? El algoritmo para todos los valores es trivial utilizando condiciones o bucles, por lo que no estoy interesado en eso.
El diseño del algoritmo suele ser un punto débil para mí, así que no tengo idea de si mi algoritmo es "tan bueno como se puede" cuando solo se utilizan operaciones matemáticas/bit a bit. Gracias
¡Eso es bastante astuto! De vez en cuando necesito manipular cadenas de bits de tamaño extraño en un entorno en el que cada ciclo cuenta. Me aseguraré de agregar esto a mi bolsa de trucos. –
Debo advertir que solo he realizado algunas pruebas superficiales, por lo que no puedo garantizar que este método funcione 100% – GRB
Podría ser más seguro usar unsigned int para evitar cualquier negocio divertido con bits de signo. –