How to efficiently store values, and benefit?

Essentially, I have an array of 3 sets of values, 0-3. I can store the 4 values in 2 bits, yeah? And each 3 values are related to each other - they represent rotation on X, Y, or Z. My question is, how would I go about storing these values in a single container in an array - preferably not a class as those add overhead?

Also, is there a gain in performance to storing and getting the values from these bits? Right now, I’m storing the values in a 4-dimensional byte array, as I have a 3D array of 3 values for each X, Y, and Z in space. I might just be jumping the gun, but this seems like bad practice to me. I’ve considered writing a utility class that uses a BitSet, but I’ve heard that those aren’t all they’re cracked up to be, simple though it might be.

For the former, original question, what I have boiled it down to is that I need to use bitshifting (> and <) as well as masking AND and OR in order to shift.


public void setBit(byte b, int pos, boolean truth) {
    if (truth) {
        b |= (1 << pos);
    }
    else {
        b &= ~(1 << pos);
    }
}

It’s kinda messy and that’s only how to SET the bits - I’m still unsure of how to read specific bits.

For the second method with the BitSet, it would be much easier - every six bits = the three 2-bit values, offset by 6 * whatever. But I don’t know if it’s a viable method, as the array size that I calculate I need for the values per “chunk” of data is like, ~3KB in bits alone. It would still be miles easier though… I think?

Sorry if anything is kinda oddly-worded!

How many values are you storing? How frequently are they accessed? Are you targetting PC or Android? Very likely, you do not need to introduce this complexty.

You simply do not need to do this for anything these days. Even network traffic. Even if you want millions of entities. Also it can be a lot slower. On modern architectures wasting memory for correct alignment is worth it.

But as a programmer you just shouldn’t bother with such minor and irrelevant details. Get a game working first.

such bit format is still very useful. storing a 1024^3 boolean space in a file is either 1GB (8bit) or 128MB (1bit), quiet good to me.

boolean getBit(byte b, int pos)
{
  return (( b>>>pos ) & 1 ) != 0
}

// write a sequence of len*truth into byte b at position pos. len must be <= 8 - pos
boolean putBits(byte b, int pos, int len, boolean truth)
{
  p |= (byte)(( (truth?1:0) & (( 1<<len ) - 1 ))<<pos);
}

i think as a programmer it is important to throw such thing into your toolbox and use it when appropriate. not to optimize premature, but rather to avoid refactoring-hell later on.

o/

If you really must do this. Stick with BitSets that is already done and debugged for you.

The golden rule for any programmer should always be “has some other sucker already done this for me?”

But before that, the programmer should ask “Do I even need to do this?”.

I interpret your question as that you have 3 values which are in the range 0-3 (2 bits each) and want to know how to store them as compact as possible. First of all, you only have 3*2 = 6 bits which means that a byte is more then enough. (Actually you can save 4 values like this in one byte). Anyway this can be done with shifting. Example code provided below.


	public static void main(String[] args)
	{
		byte b = saveValues(3, 0, 2);  // save 3, 0 and 2 in a byte
		showValues(b);  // read them back and print them
	}

	static byte saveValues(int x, int y, int z)
	{
		byte result = 0;
		result |= ((x)); // assuming x,y,z really are in the range 0-3 
		result |= ((y << 2)); // shift y two bits up relative to x so they don't overlap 
		result |= ((z << 4)); // shift z four bits up relative to x and two bits up relative to x so they don't overlap 

		return result;  
	}

	static void showValues(byte b)
	{
		int x, y, z;

		x = b & 0x3; // & the mask 0x3 is for keeping the two relevant bits 
		y = (b >> 2) & 0x3;  // shift back down the same amount as it were shifted up at saving ...
		z = (b >> 4) & 0x3; 

		System.out.println("x = " + x); // the 3 lines above could be merged into these, but for readability they're on their own
		System.out.println("y = " + y);
		System.out.println("z = " + z);

	}

In the code for saving, the two bits for y and z is shifted to its position in the byte. At decoding the process is reversed (they are shifted back) and excess bits (from the other variables are masked away with the bit mask 0x3 which is the same as …000000011, only two bits set). Doing all this work is a bit time consuming, and probably should only be done when storing and reading from a very space constrained storage and where the processing time doesn’t matter… For a computer this would probably only be beneficial when saving excessive amounts of these values to a file on order to save hard drive space/time spent writing data to the hard drive.