2010-05-23 13 views
8

Si vous avez le numéro binaire 10110, comment puis-je l'obtenir pour retourner 11111? par exemple, un nouveau nombre binaire qui définit tous les bits à 1 après la première 1, il y a des exemples De même, dans la liste ci-dessous:Obtenir la longueur des bits utilisés dans int

101 doit retourner 111 (longueur de 3 bits) 011 doit revenir 11 (longueur de 2 bits) 11100 devrait be return 11111 (longueur de 5 bits) 101010101 devrait renvoyer 111111111 (longueur de 9 bits)

Comment cela peut-il être obtenu le plus facilement en Java? Je pourrais trouver quelques méthodes mais elles ne sont pas très "jolies".

+3

C'est ici: http://graphics.stanford.edu/~seander/bithacks.html –

Répondre

6

Vous pouvez utiliser:

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

L'idée est que 1 va plus à gauche sont copiés à tous les postes sur la droite.

EDIT: Fonctionne également très bien avec un négatif value. Si vous remplacez int par long, ajoutez une instruction |= supplémentaire: value |= (value >> 32). En général, le dernier décalage doit être une puissance de 2 qui est au moins la moitié de la taille en bits.

+2

Ce qui est particulièrement agréable avec cet algorithme, c'est qu'il réutilise les opérations précédentes. Naïvement j'aurais juste fait 32 quarts de travail. –

+1

Si vous regardez l'implémentation de 'Integer # highestOneBit()' dans le JDK, vous verrez le même algorithme, bien que la dernière étape soit personnalisée ne délivrant qu'un seul bit, nécessitant la défaite capturée dans la réponse de hleinone. – seh

6

ai pas testé, mais quelque chose comme ça devrait être correct: ce code

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

+1 pour penser en dehors de la boîte :-) –

+1

Cela ne fonctionnera pas si ' nombre' est négatif. Ce sera rapide si 'number' est habituellement petit, mais lent si' number' est à peu près uniformément réparti sur sa portée. – doublep

+0

Vraiment sur les points négatifs, je n'y ai pas pensé. Et ce serait plus rapide en moyenne si je partais de l'autre côté. Mais 63 itérations (max) ne sont pas vraiment si lentes; et la réponse était sur le dessus de ma tête. Évidemment, la solution de Hleinone le fait sortir de l'eau ... :) – Amadan

0

Pas le plus efficace, mais simple,

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

Il travaillera pour la première 31 bits d'int et le premier 63 bit pour longtemps.

10
+0

Pour l'exhaustivité: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Integer.html#highestOneBit(int) – Eric

+0

Hmmm .. On dirait que je ne peux pas poster le lien. SO n'aime pas les supports. – Eric

+3

Wow, je n'avais aucune idée que Java avait cette fonction ... c'est définitivement le plus élogieux ici. – Amadan