2010-05-23 21 views
8

Si tiene el número binario 10110, ¿cómo puedo obtener que devuelva 11111? por ejemplo, un nuevo número binario que establece todos los bits a 1 después de la primera 1, hay algunas igualmente ejemplos enumerados a continuación:Obtener la longitud de los bits utilizados en int

101 debe devolver 111 (longitud de 3 bits) 011 deben regresar 11 (longitud de 2 bits) 11100 debe be return 11111 (longitud de 5 bits) 101010101 debe devolver 111111111 (longitud de 9 bits)

¿Cómo se puede obtener esto de la manera más fácil en Java? Podría encontrar algunos métodos, pero no son muy "bonitos".

+3

Todo está aquí: http://graphics.stanford.edu/~seander/bithacks.html –

Respuesta

6

podría utilizar este código:

int setBits (int value) 
{ 
    value |= (value >> 1); 
    value |= (value >> 2); 
    value |= (value >> 4); 
    value |= (value >> 8); 
    value |= (value >> 16); 
    return value; 
} 

La idea es que más a la izquierda 1 obtendrá copiado en todas las posiciones en el derecho.

EDITAR: También funciona bien con un negativo value. Si reemplaza int con long, agregue una declaración adicional de |=: value |= (value >> 32). En general, el último turno debe ser una potencia de 2 que sea al menos la mitad del tamaño de value en bits.

+2

Lo que es especialmente bueno con ese algoritmo es que reutiliza las operaciones anteriores. Ingenuamente solo habría hecho 32 turnos. –

+1

Si nos fijamos en la implementación de 'Integer # highestOneBit()' en el JDK, verá el mismo algoritmo, aunque el último paso está diseñado para entregar solo un bit, lo que requiere la operación de deshacer la respuesta de hleinone. – seh

6

no hemos probado, pero algo como esto debe estar bien:

long setBits(long number) { 
    long n = 1; 
    while (n <= number) n <<= 1; 
    return n - 1; 
} 
+0

1 por pensar fuera de la caja :-) –

+1

Esto no funcionará si ' number' es negativo. Será rápido si 'number' es generalmente pequeño, pero lento si' number' se distribuye uniformemente en su rango. – doublep

+0

Cierto sobre los negativos, no pensé en eso. Y sería más rápido en promedio si comenzara desde el otro extremo. Pero 63 iteraciones (max) no son realmente tan lentas; y la respuesta estaba fuera de mi cabeza. Obviamente, la solución de hleinone lo saca del agua ... :) – Amadan

0

No más eficiente, pero más simple,

int i = (1 << (int)(Math.log(n)/Math.log(2)+1)) - 1; 

Se trabajará para la primera 31 bits de int y la primera 63 bits por mucho tiempo.

10
+0

Para completar: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Integer.html#highestOneBit(int) – Eric

+0

Hmmm .. Parece que no puedo publicar el enlace. SO no le gustan los corchetes. – Eric

+3

Guau, no tenía idea de que Java tenía esta función ... esto es definitivamente más elegante aquí. – Amadan

Cuestiones relacionadas