2010-03-18 13 views
42

Wenn ich eine ganze Zahl habe, die ich Bit Manipulation ausführen möchte, wie kann ich es in java.util.BitSet laden? Wie kann ich es zurück in einen Int oder Long konvertieren? Ich bin nicht so besorgt über die Größe der BitSet - es wird immer 32 oder 64 Bit lang sein. Ich möchte nur die Methoden set(), clear(), nextSetBit() und nextClearBit() anstelle von bitweisen Operatoren verwenden, aber ich kann keinen einfachen Weg finden, ein mit einem numerischen Typ gesetztes Bit zu initialisieren.BitSet zu und von Integer/Long

+1

Persönlich würde ich sagen, dass rohe Bit-Manipulation der Weg ist, hier zu gehen. Es ist wirklich nicht so kompliziert, und wie Sie sagen, sehe ich keinen einfachen Weg, um einen Int oder Long in ein BitSet zu bekommen. –

Antwort

47

Der folgende Code erstellt ein wenig von einem Long-Wert und umgekehrt gesetzt:

public class Bits { 

    public static BitSet convert(long value) { 
    BitSet bits = new BitSet(); 
    int index = 0; 
    while (value != 0L) { 
     if (value % 2L != 0) { 
     bits.set(index); 
     } 
     ++index; 
     value = value >>> 1; 
    } 
    return bits; 
    } 

    public static long convert(BitSet bits) { 
    long value = 0L; 
    for (int i = 0; i < bits.length(); ++i) { 
     value += bits.get(i) ? (1L << i) : 0L; 
    } 
    return value; 
    } 
} 

EDITED: Jetzt beide Richtungen, @leftbrain: der Ursache, Sie haben Recht

+6

Ich denke, die Zeile (Wert% 1L! = 0) sollte sein (Wert% 2L! = 0) –

+0

'if (Wert & 1! = 0)' wie wir prüfen wollen, ob das 0 Bit gesetzt ist, '%' ist modulo operator, und 'es ist immer 0, da alle Zahlen durch 1 teilbar sind – ithkuil

+1

FYI, das schafft ein Bitset in Little-Endian-Reihenfolge –

-2

Ist nicht die public void set(int bit) Methode, wonach Sie suchen?

+6

Das setzt ein einzelnes Bit mit dem von Ihnen angegebenen Index. Ich möchte jedes Bit setzen, das in der Ganzzahl gesetzt ist. – ataylor

17

Java 7 hat BitSet.valueOf(byte[]) und BitSet.toByteArray()

wenn Sie mit Java 6 oder früher stecken geblieben sind, können Sie BigInteger verwenden, wenn es nicht wahrscheinlich ist ein Performance-Engpass sein - es hat getLowestSetBit, setBit und clearBit Methoden (die letzten beide ein neues BigInteger statt Modifizierung an Ort und Stelle erstellen.)

1

ziemlich direkt aus der Dokumentation von nextSetBit

value=0; 
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { 
value += (1 << i) 
} 
+0

Dies wird bei einem BitSet, das größer als 32 oder 64 Bits ist, fehlschlagen. In diesem Fall müssen Sie am Ausgang ein 'int []' oder 'long []' verarbeiten. Aber OP ist das ganz und gar egal, also fair genug. Nur ein paar kleinere Pannen: Im Falle einer langen sollten Sie '1L << i', um Überlauf zu verhindern, und ein OR wie 'Wert | = 1L << i' ist genug. – charlie

3

Um ein long zurück von einem kleinenBitSet in einem 'streamy' Weg:

long l = bitSet.stream() 
     .takeWhile(i -> i < Long.SIZE) 
     .mapToLong(i -> 1L << i) 
     .reduce(0, (a, b) -> a | b); 

Umgekehrt:

BitSet bitSet = IntStream.range(0, Long.SIZE - 1) 
     .filter(i -> 0 != (l & 1L << i)) 
     .collect(BitSet::new, BitSet::set, BitSet::or); 

N.B .: Mit BitSet::valueOf und BitSet::toLongArray ist natürlich einfacher.