BitArray (compacting 32 bool values into one integer)

Posted on

Problem

I’m trying to refamiliarize myself with Java and working with it, so I’ve implemented my own version of a BitArray. Basically, it’s an array of integers that maps 32 boolean values to each integer. This means an array of 32 boolean values only takes 4 bytes of space.

I was attempting to implement a Sieve of Eratosthenes and I figured I should implement a BitArray at the same time.

So, the BitArray class is as follows:

public class BitArray {
    private int[] elements;
    private int length;

    public boolean get(int index) {
        return (elements[(int)Math.floor(index / 32f)] >> (index % 32) & 0x01) == 1;
    }

    public void set(int index, boolean value) {
        int actualIndex = (int)Math.floor(index / 32f);
        int elementValue = elements[actualIndex] & ~(0x01 << (index % 32));

        if (value) {
            elementValue = elementValue | (0x01 << (index % 32));
        }

        elements[actualIndex] = elementValue;
    }

    public int getLength() {
        return length;
    }

    public BitArray(int maxSize) {
        length = maxSize;
        elements = new int[(int)Math.ceil(maxSize / 32f)];
    }
}

And to test this BitArray out, I implemented the following code:

public class Main {
    public static void main(String[] args) {
        int maxValue = 10000;

        // All the values will be initialized as false. If we mark them true, it means they are a composite number.
        BitArray bitArrayValues = new BitArray(maxValue);

        for (int i = 2; i < Math.sqrt(bitArrayValues.getLength()); i++) {
            if (!bitArrayValues.get(i)) {
                for (int j = i * i; j < bitArrayValues.getLength(); j += i) {
                    bitArrayValues.set(j, true);
                }
            }
        }

        // All the values will be initialized as false. If we mark them true, it means they are a composite number.
        boolean[] boolArrayValues = new boolean[maxValue];

        for (int i = 2; i < Math.sqrt(boolArrayValues.length); i++) {
            if (!boolArrayValues[i]) {
                for (int j = i * i; j < boolArrayValues.length; j += i) {
                    boolArrayValues[j] = true;
                }
            }
        }

        // Print all the numbers which are still false, which indicates the number is a prime.
        for (int i = 1; i < bitArrayValues.getLength(); i++) {
            if (!bitArrayValues.get(i)) {
                System.out.println(i + " is prime");
            }
        }

        boolean pass = true;

        for (int i = 0; i < maxValue; i++) {
            if (boolArrayValues[i] != bitArrayValues.get(i)) {
                pass = false;
            }
        }

        System.out.println("Arrays are equal? " + pass);
        System.out.println("Done.");
    }
}

I had some trouble getting back into the Java mindset for this, after having done C# and VB.NET for so long. Overall I think it was a successful adventure.

Any comments on either code block are welcome.

Solution

public void set(int index, boolean value) {
    int actualIndex = (int)Math.floor(index / 32f);
    int elementValue = elements[actualIndex] & ~(0x01 << (index % 32));

    if (value) {
        elementValue = elementValue | (0x01 << (index % 32));
    }

    elements[actualIndex] = elementValue;
}

You can avoid a bit of recalculation here by caching the shift value. Also, switch to long to increase the range of values the user can enter

public void set(long index, boolean value) {
    final long actualIndex = (long)Math.floor(index / 32f);
    final long mask = 0x01 << (index % 32);
    long elementValue = elements[actualIndex] & ~mask;

    if (value) {
        elementValue |= mask;
    }

    elements[actualIndex] = elementValue;
}

Leave a Reply

Your email address will not be published. Required fields are marked *