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
Odpowiedz
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ę
Myślę, że linia (wartość% 1L! = 0) powinna być (wartość% 2L! = 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
FYI, to jest tworzenie bitsetu w małym-endianowym rozkazie –
Czy metoda public void set(int bit)
nie jest tym, czego szukasz?
Ustawia jeden bit z indeksem, który podasz. Chciałbym ustawić każdy bit ustawiony w liczbie całkowitej. – ataylor
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).
Dodaj do finnw odpowiedź: istnieją również BitSet.valueOf(long[])
i BitSet.toLongArray()
. Więc:
int n = 12345;
BitSet bs = BitSet.valueOf(new long[]{n});
long l = bs.toLongArray()[0];
Prawie prosto z dokumentacją nextSetBit
value=0;
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
value += (1 << i)
}
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
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.
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. –