2016-11-12 1 views
0

Si j'ai un Java BitSet d'une longueur de 500 bits et, je sais, il contient 100 entiers, chacun étant représenté par 5 bits, comment puis-je extraire un tableau de ces entiers? En utilisant certains des exemples en ligne, je suis venu avec ce qui suit:Java: Extraction d'entiers à partir d'un BitSet dont chacun consiste en un bit spécifique

static int[] bitSet2Ints(BitSet bs, int bitNumber) 
    { 
     int[] temp = new int[bs.length()/bitNumber]; 

     for (int i = 0; i < temp.length; i++) 
     { 
      for (int j = 0; j < bitNumber; j++) 
      { 
       if (bs.get(i * bitNumber + j)) 
       { 
        temp[i] |= 1 << j; 
       } 
      } 
     } 

     return temp; 
    } 

Je me demandais si cela est la bonne façon de le faire.

Merci!

EDIT: Apparemment, le code ne produit pas le résultat attendu. Je l'ai fait un test unitaire et l'entrée et la sortie étaient complètement différentes:

Ceci est mon entrée:

Binary String: 0 is 00000 
Binary String: 1 is 00001 
Binary String: 2 is 00010 
Binary String: 3 is 00011 
Binary String: 4 is 00100 
Binary String: 5 is 00101 
Binary String: 6 is 00110 
Binary String: 7 is 00111 
Binary String: 8 is 01000 
Binary String: 9 is 01001 
Binary String: 10 is 01010 
Binary String: 11 is 01011 
Binary String: 12 is 01100 
Binary String: 13 is 01101 
Binary String: 14 is 01110 
Binary String: 15 is 01111 
Binary String: 16 is 10000 
Binary String: 17 is 10001 
Binary String: 18 is 10010 
Binary String: 19 is 10011 
Binary String: 20 is 10100 
Binary String: 21 is 10101 
Binary String: 22 is 10110 
Binary String: 23 is 10111 
Binary String: 24 is 11000 
Binary String: 25 is 11001 
Binary String: 26 is 11010 
Binary String: 27 is 11011 
Binary String: 28 is 11100 
Binary String: 29 is 11101 
Binary String: 30 is 11110 
Binary String: 31 is 11111 

Ceci est ma sortie:

NUMBER OF VALUES EXTRACTED: 32 
INTEGER CONVERTED: 0 
INTEGER CONVERTED: 16 
INTEGER CONVERTED: 8 
INTEGER CONVERTED: 24 
INTEGER CONVERTED: 4 
INTEGER CONVERTED: 20 
INTEGER CONVERTED: 12 
INTEGER CONVERTED: 28 
INTEGER CONVERTED: 2 
INTEGER CONVERTED: 18 
INTEGER CONVERTED: 10 
INTEGER CONVERTED: 26 
INTEGER CONVERTED: 6 
INTEGER CONVERTED: 22 
INTEGER CONVERTED: 14 
INTEGER CONVERTED: 30 
INTEGER CONVERTED: 1 
INTEGER CONVERTED: 17 
INTEGER CONVERTED: 9 
INTEGER CONVERTED: 25 
INTEGER CONVERTED: 5 
INTEGER CONVERTED: 21 
INTEGER CONVERTED: 13 
INTEGER CONVERTED: 29 
INTEGER CONVERTED: 3 
INTEGER CONVERTED: 19 
INTEGER CONVERTED: 11 
INTEGER CONVERTED: 27 
INTEGER CONVERTED: 7 
INTEGER CONVERTED: 23 
INTEGER CONVERTED: 15 
INTEGER CONVERTED: 31 
+0

00001 ne devrait pas convertir en 1? C'est par exemple ce que Integer.parse ("00001", 2) produirait. – TheConstructor

+0

Exactement, TheConstructor! Mais le code inclus (le vôtre et le mien) produit 16 à la place. –

Répondre

1

Quel type de « correct » sommes-nous parler ici?

Votre code semble très bien, et semble être une solution parfaitement raisonnable à votre problème. Si cela ne tenait qu'à moi, j'aurais écrit quelque chose d'un peu moins imbriqué, pour le rendre plus facile à lire. Peut-être quelque chose comme ceci:

static byte[] bitSet2Ints(BitSet bs, int bitNumber) { 
    byte[] temp = new byte[bs.length()/bitNumber]; 

    for (int i = 0; i < temp.length; i++){ 
     temp[i] = bs.get(i * bitNumber, (i + 1) * bitNumber).toByteArray()[0]; 
    } 

    return temp; 
} 

* ont pas testé ce code

Vous pouvez également ajouter des contrôles de paramètres pour éviter une entrée non valide:

if (bs == null){ 
     throw new NullPointerException("The bit set cannot be null!"); 
    } 
    if (bitNumber <1 || bitNumber > 7){ 
     throw new IllegalArgumentException("Illegal bit count"); 
    } 
+0

Vous pouvez également utiliser toLongArray. Il prend en charge plus de nombres de bits et est probablement moins cher car BitSet utilise en interne un long [] pour stocker les données. – TheConstructor

+0

@TheConstructor la question était sur les nombres de 5 bits, donc un octet fera l'affaire. Je ne sais pas si «long» serait moins cher, c'est quelque chose que vous auriez besoin de comparer. – Malt

+0

bien sûr, vous aurez besoin de comparer les solutions pour être certain. Cela peut aussi dépendre de savoir si un int [] doit être retourné et bitNumber est toujours 5. – TheConstructor

1

Je suppose que @Malt déjà donné la solution la meilleure lisibilité. J'espère que c'est la solution la plus rapide car get(int, int) crée un autre BitSet et vérifier chaque bit lui-même a trop de chemins CPU.

je vais copier la représentation interne du BitSet à une nouvelle long -array puis recourir à arithmethics entiers binaires pour obtenir des sections consécutives de bitNumber morceaux.

static int[] bitSet2Ints(BitSet bs, int bitNumber) { 
    if (bitNumber < 1 || bitNumber > Integer.SIZE) { 
     throw new IllegalArgumentException("bitNumber needs to be between 1 and " + Integer.SIZE); 
    } 

    int mask = 0; 
    for (int i = 0; i < bitNumber; i++) { 
     mask = mask << 1 | 1; 
    } 

    long[] longArray = bs.toLongArray(); 
    int[] result = new int[bs.length()/bitNumber]; 
    for (int i = 0; i < result.length; i++) { 
     final int globalStartBit = i * bitNumber; 
     final int localStartBit = globalStartBit % Long.SIZE; 
     result[i] = (int) (longArray[globalStartBit/Long.SIZE] >>> localStartBit) & mask; 
     if (Long.SIZE - localStartBit < bitNumber) { 
      result[i] |= (int) (longArray[globalStartBit/Long.SIZE + 1] << Long.SIZE - localStartBit) & mask; 
     } 
    } 

    return result; 
} 

Comme >>> cycles autour des bits, vous pouvez utiliser globalStartBit avec et comme << cycles, aussi, vous pouvez utiliser simplement - localStartBit comme argument droit.

+0

Merci, TheConstructor. Votre code produit les mêmes résultats que dans la question, mais il semble plus solide. –

+0

Apparemment, le code ne produit pas le résultat attendu. S'il vous plaît voir la question éditée. –