Tal vez pueda ayudarme con el siguiente problema que puede ayudarme a acelerar un administrador de memoria en el que estoy pensando (no estoy seguro de que exista una solución, no encontré una).
Tengo un registro de 32 bits y necesito encontrar si hay n bits establecidos consecutivos en él y, de ser así, cuál es su compensación. Por ejemplo, si el registro tiene el siguiente valor 1111000000000000000000001111111000 y n es igual a 4, se acepta cualquiera de las siguientes respuestas (las compensaciones comienzan desde 0):
3, 4, 5, 6, 28
Las operaciones atómicas que tengo son todas las operaciones bit a bit regulares (&, |, ~, …) y también encontrar el desplazamiento de bit menos significativo (3 en el registro anterior). El algoritmo (suponiendo que exista) no debe tomar más de 5 operaciones atómicas.
Solución del problema
Si hay un algoritmo que hace eso, entonces la complejidad del peor de los casos es al menos O(m-n)
, donde m
es el número de bits en el registro y n
es el número de bits de conjunto consecutivos que está buscando. Esto es fácil de ver porque si todos los bits están configurados, su algoritmo tendrá que generar m-n
elementos exactos, por lo que su complejidad no puede ser menor.
EDITAR
Hay una solución elegante para un problema similar aquí Recorriendo bits en un número entero, ruby , encontrando la longitud de la 1
secuencia longes.
Si sabe n
de antemano la duración de la carrera que está buscando, este algoritmo requerirá solo n
pasos. Luego, el desplazamiento se puede recuperar a partir del número de ceros finales en el preúltimo paso del algoritmo en aproximadamente 5 pasos más. Eso no es extremadamente eficiente, pero probablemente sea mejor que la solución de bucle, especialmente para un pequeño archivo n
.
EDITAR 2
Si n
se conoce de antemano, podemos calcular una secuencia de turnos necesarios para ello. Por ejemplo, si estamos buscando ejecuciones de 7 bits, entonces tendríamos que hacer
x &= x >> 1
x &= x >> 3
x &= x >> 1
x &= x >> 1
El punto es que cambiamos los n/2
bits a la derecha si n
es par o por 1 si n
es impar, luego actualizamos n
en consecuencia (cualquiera n = n - 1 or n = n / 2
), como sugiere @harold. Estimar estos valores sobre la marcha sería costoso, pero si los calculamos previamente, será bastante eficiente.
EDITAR 3
Aún mejor, para cualquier n
, se requerirían pasos exactos ceil(log(2,n))
, sin importar el turno que tomemos, siempre que sea entre floor(n/2)
y 2^floor(log(2,n-1))
. Vea los comentarios a continuación.
No hay comentarios.:
Publicar un comentario