4

I'm not very familiar with all the bit shifting and masks that are involved with the process but I have a vague idea.

I'm looking for a way to pack around 30 booleans into an int or long so I can send the packed data through one data type, rather than sending across 30 separate booleans. Either this if it's possible, or the use of a bit set might help. I was wondering if someone could give me a little insight into how to go about packing the values.

kbz
  • 984
  • 2
  • 12
  • 30
  • the most novice technique i would do If the ordering doesn't matter than I would simply append 0 and 1's boolean results to a string and send it over. – iCurious Sep 13 '15 at 14:08
  • all the answers below dose make sense, however how are you intending to read this data structure of ones and zeros ? – QuakeCore Sep 13 '15 at 14:15
  • 1
    possible duplicate of [BitSet to and from integer/long](http://stackoverflow.com/questions/2473597/bitset-to-and-from-integer-long) –  Sep 13 '15 at 14:21
  • I'm looking for the most efficient way of doing it and of course for learning purposes as I don't know much about bit manipulation, and yes they need to be ordered and they need unpacking when they are received so the values can be used. – kbz Sep 13 '15 at 14:23

4 Answers4

7

If you have an int (32 bits), you can set, clear, and check the N'th (0-31) bit like this:

int bits = 0;

// Set bit n
bits |= 1 << n;

// Clear bit n
bits &= (1 << n) ^ -1;

// Check bit n
if ((bits & 1 << n) != 0) { /*bit was set*/ }

So, to convert a boolean array into a bitmask:

boolean[] bools = /*allocated elsewhere, max. length: 32*/;

int bits = 0;
for (int i = 0; i < bools.length; i++)
    if (bools[i])
        bits |= 1 << i;

And to convert a bitmask to a boolean array:

int bits = /*assigned elsewhere*/;

boolean[] bools = new boolean[30]; /*max. length: 32*/
for (int i = 0; i < bools.length; i++)
    if ((bits & 1 << i) != 0)
        bools[i] = true;
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Hi, thanks for the demo. As I'm doing this for learning purposes also, could you please explain the shifting that is going on here? like if ((bits & 1 << i) != 0), I get that it's checking if a certain bit is equal to one, but what does the & 1 << i mean? – kbz Sep 13 '15 at 19:11
3

A boolean represents a bit of information, 30 booleans represent 30 bits of information. Build an int (32 bits), send it, job done.

May not be the best approach, but just to give you an idea

    int i=0;
    boolean[]a = {true,false,true,false,false,false,false};
    for(boolean b:a)i=i*2+(b?1:0);
    System.out.println(Integer.toBinaryString(i));

prints

    1010000
Luigi Cortese
  • 10,841
  • 6
  • 37
  • 48
  • Thanks, and yes I gathered this, but I was more concerned about the packing/unpacking or the "building" aspect – kbz Sep 13 '15 at 14:11
0

If you have a list of booleans Boolean b[30] you can declare an int x = 0 and iterate through b and for every iteration do x = x*2 // move to next bit and x = x+1 // if b is true

    Boolean b[30];  // assign values to array...
    int x = 1;
    for (int i=0; i<30; i++){
        if (b[i] == true ){
            x = x+1;
        }
        x = x*2;
    }

Now, you can go over x and check the 30 bits, after the first. When a bit equals 1 it means the corresponding boolean was true. The first bit was initilized as 1, so this would work, even if the first bool is false

CIsForCookies
  • 12,097
  • 11
  • 59
  • 124
  • That works. Would this work for the unpacking too as I've got to read the data back and verify it when it reaches the server – kbz Sep 13 '15 at 14:12
  • your result int would be like: 1 <<- prefix (don't use) and then 30 bits that are "1" for true and "0" for false. divide the int by 2 and check it LSB using x & 1 – CIsForCookies Sep 13 '15 at 14:18
0

Try this:

    boolean b[] = new boolean[32];
    b[2] = true;
    b[31] = true;
    int m = 0x01;
    int n = 0;
    for(int j = b.length - 1; j >=0; j--) {
        if(b[j]) n |= m;
        m = (m<< 1);
    }
    System.out.println(Integer.toBinaryString(n));
    // Output: 100000000000000000000000000001

And I guess you can unpack by & instead of |

dragon66
  • 2,645
  • 2
  • 21
  • 43