2010-03-18 14 views
42

Jeśli mam liczbę całkowitą, którą chciałbym poddać nieco manipulacji, jak mogę ją załadować do java.util.BitSet? Jak mogę przekonwertować go z powrotem na int lub długi? Nie martwię się wielkością BitSet - zawsze będzie to 32 lub 64 bity. Chciałbym raczej użyć metod raczej niż operatory bitowe, ale nie mogę znaleźć łatwego sposobu inicjowania zestawu bitów za pomocą typu liczbowego.BitSet do iz liczby całkowitej/długi

+1

Osobiście, powiedziałbym, że surowa manipulacja bitem jest sposobem, aby tu dotrzeć. To naprawdę nie jest tak skomplikowane, a jak mówisz, nie widzę prostego sposobu na uzyskanie int lub long w zestawie bitowym. –

Odpowiedz

47

Poniższy kod tworzy bitu od dłuższego wartości i odwrotnie:

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; 
    } 
} 

edycja: Teraz obu kierunkach, @leftbrain: przyczyny, masz rację

+6

Myślę, że linia (wartość% 1L! = 0) powinna być (wartość% 2L! = 0) –

+0

'jeśli (wartość i 1! = 0)', ponieważ chcemy sprawdzić, czy ustawiony jest 0 bit, '%' jest operatorem modulo i "zawsze jest 0, ponieważ wszystkie liczby są podzielne przez 1 – ithkuil

+1

FYI, to jest tworzenie bitsetu w małym-endianowym rozkazie –

-2

Czy metoda public void set(int bit) nie jest tym, czego szukasz?

+6

Ustawia jeden bit z indeksem, który podasz. Chciałbym ustawić każdy bit ustawiony w liczbie całkowitej. – ataylor

17

Java 7 i ma BitSet.valueOf(byte[])BitSet.toByteArray()

Jeśli utkniesz z Java 6 lub wcześniej, można użyć BigInteger jeśli nie jest prawdopodobne, aby być wąskim gardłem wydajności - ma getLowestSetBit, setBit i clearBit metody (dwa ostatnie stworzy nowy BigInteger zamiast modyfikowania in-place).

1

Prawie prosto z dokumentacją nextSetBit

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

To się nie powiedzie dla BitSet większego niż 32 lub 64 bity, w takim przypadku będziesz musiał obsłużyć 'int []' lub 'long []' na wyjściu. Ale OP wyraźnie nie dba o to, tak sprawiedliwie. Kilka drobnych usterków: w przypadku długiego powinieneś "1L << i", aby zapobiec przepełnieniu, a OR, jak "wartość | = 1L << i" wystarcza. – charlie

3

Aby uzyskać long wróciłem z małejBitSet w 'Streamy' sposób:

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

odwrotnie:

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

N.B .: Korzystanie z BitSet::valueOf i BitSet::toLongArray jest oczywiście łatwiejsze.