BitSet to and from integer/long
The following code creates a bit set from a long value and vice versa:
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: Now both directions, @leftbrain: of cause, you are right
Handling Long data with BitSet in Java
BitSet
could be used by seeing which bits were previously set. That would then constitute a duplicate value. However, you can't set a bit position greater than Integer.MAX_VALUE (and it would be infeasible to handle such a large range for longs). So it would not work for the range you suggested. And I presume you would still want to record the duplicates.
I would use a Map<Long,Long>
to do a frequency count. Then you can just determine the exact count of each value provided. And locating the next Key of a map is comparable to calculating which internal long value holds the desired bit. So I don't believe performance is a factor here.
If you simply want to eliminate duplicates, then just put them in a Set<Long>
Based on your comment, check out this simple test for holding one large value in a BitSet.
BitSet bitSet = new BitSet();
bitSet.set(Integer.MAX_VALUE);
long[] backingArray = bitSet.toLongArray();
System.out.printf("Size of backing array = %,d longs.%n",backingArray.length);
Prints
Size of backing array = 33,554,432 longs.
Convert a byte or int to bitset
If you want a BitSet, try:
final byte b = ...;
final BitSet set = BitSet.valueOf(new byte[] { b });
If you want a boolean[]
,
static boolean[] bits(byte b) {
int n = 8;
final boolean[] set = new boolean[n];
while (--n >= 0) {
set[n] = (b & 0x80) != 0;
b <<= 1;
}
return set;
}
or, equivalently,
static boolean[] bits(final byte b) {
return new boolean[] {
(b & 1) != 0,
(b & 2) != 0,
(b & 4) != 0,
(b & 8) != 0,
(b & 0x10) != 0,
(b & 0x20) != 0,
(b & 0x40) != 0,
(b & 0x80) != 0
};
}
Java from BigInteger to BitSet and back
You can use the BigInteger.toByteArray()
and BitSet.toByteArray()
for these:
BigInteger bi = new BigInteger("31415926535");
bi = bi.multiply(new BigInteger("271828"));
System.out.println(bi);
BitSet bs = BitSet.valueOf(bi.toByteArray());
System.out.println(bs);
BigInteger bi2 = new BigInteger(bs.toByteArray());
System.out.println(bi2);
You can use the constructor of the BigInteger(byte[])
to convert the array of bytes into a BigInteger
and the BitSet.valueOf(byte[])
to convert the data into the desired values.
For the given code, it outputs:
8539728478155980
{1, 2, 3, 4, 9, 10, 12, 14, 17, 18, 20, 22, 23, 25, 27, 28, 29, 30, 32, 33, 35, 37, 38, 42, 44, 45, 50, 51, 54, 55}
8539728478155980
Note that the 2-complement notation is used. Thus for negative numbers, it will generate additional ones. And a 2^64-1
will require more than 64
bits to represent. This also works with big endian. (see modified answer below).
EDIT: there is however one problem with this approach: if there are tailing zeros, these are not taken into account by the program. This can be important because they are part of the representation. You can solve this problem by adding a tailing bit:
public static BitSet convertTo (BigInteger bi) {
byte[] bia = bi.toByteArray();
int l = bia.length;
byte[] bsa = new byte[l+1];
System.arraycopy(bia,0,bsa,0,l);
bsa[l] = 0x01;
return BitSet.valueOf(bsa);
}
public static BigInteger convertFrom (BitSet bs) {
byte[] bsa = bs.toByteArray();
int l = bsa.length-0x01;
byte[] bia = new byte[l];
System.arraycopy(bsa,0,bia,0,l);
return new BigInteger(bia);
}
And call it with:
BigInteger bi = new BigInteger("20000000");
System.out.println(bi);
BitSet bs = convertTo(bi);
System.out.println(bs);
BigInteger bi2 = convertFrom(bs);
System.out.println(bi2);
About the memory usage
In general both methods will use approximately the same number of bits. For the first implementation (without size marker and thus errors), it is possible that sometimes, the BitSet
approach will use one byte less than the BigInteger
approach. With the size marker (second approach), it is the opposite: in general the BitSet
will use always one extra byte, except for some rare occasions.
How to input an integer's binary expression into a bitSet in java
BitSet
has a static valueOf(long[])
method which
Returns a new bit set containing all the bits in the given long array.
So an array with one long will have 64 bits, an array with two longs will have 128 bits, etc.
If you only need to get a BitSet
from a single int
value, use it like so
Integer value = 42;
System.out.println(Integer.toBinaryString(value));
BitSet bitSet = BitSet.valueOf(new long[] { value });
System.out.println(bitSet);
It prints
101010
{1, 3, 5}
In other words, from the right to left in the representation above, the 2nd, 4th, and 6th bit are set.
Why is the internal data of BitSet in java stored as long[] instead of int[] in Java?
When querying or manipulating a single bit, there is no significant difference. You have to calculate the word index and read that word and, in case of an update, manipulate one bit of that word and write it back. That’s all the same for int[]
and long[]
.
One could argue that doing it using a long
instead of int
could raise the amount of memory that has to be transferred for a single bit operation if you have a real 32 bit memory bus, but since Java was designed in the nineties of the last century, the designers decided that this is not an issue anymore.
On the other hand, you get a big win when processing multiple bits at once. When you perform operations like and
, or
or xor
on an entire BitSet
, you can perform the operation on an entire word, read 64 bits, at once when using a long
array.
Similarly, when searching for the next set bit, if the bit is not within the word of the start position, subsequent words are first tested against zero, which is an intrinsic operation, even for most 32 bit CPUs, so you can skip 64 zero bits at once while the first non-zero word will definitely contain the next set bit, so only one bit extraction operation is needed for the entire iteration.
These benefits for bulk operations will outweigh any single-bit related drawbacks, if there ever are one. As said, most today’s CPU are capable of doing all operations on 64 bit words directly.
Does BitSet in java stores bits or integers?
Typically BitSet
would be implemented using a long[]
. Each long
stores 64 consecutive possible bit positions. The array needs a size equal to the highest set bit index minus one (to allow for index 0), divided by 64 (rounded down). Set bits are represented as a binary 1 and bits present in the array but not set as a binary 0.
So the internal representation of your examples would be something like:
bs1 = new long[] { 0b00010111L }; // 23
bs2 = new long[] { 0b01111110L }; // 126
// bit indexes: 76543210
(Bits 8-63 elided from constants - add all the zeros if your want.)
convert bitset to int in c++
Use to_ulong
to convert it to unsigned long
, then an ordinary cast to convert it to int
.
int mybit_int;
mybit_int = (int)(mybit.to_ulong());
DEMO
Related Topics
How to Check If a String Contains Only Digits in Java
Spring Autowiring Class VS. Interface
Problem with Assigning an Array to Other Array in Java
Java/Convert Iso-8601 (2010-12-16T13:33:50.513852Z) to Date Object
Directly Convert CSV File to JSON File Using the Jackson Library
Variable Naming Conventions in Java
Using Java Map for Range Searches
Class.Getresource() Returns Null
Running Java in Package from Command Line
Getting Class Type from String
Compare One String with Multiple Values in One Expression
Implement Converters for Entities with Java Generics
What Does Biginteger Having No Limit Mean
Does Java Support Let's Encrypt Certificates
Java: Finding the Highest Value in an Array
How to Create Change Listener for Variable
Java.Lang.Illegalstateexception: Not on Fx Application Thread; Currentthread = Thread-4