Merging bytes

M

mikew01

Hello

I need to combine 3 number values into a 2 byte array.
The value bit sizes are:

value1 = 6 bits.
value2 = 6 bits.
value3 = 12 bits.

I understand I need to use the bit manipulation operators to do this
but would like some advice on the best approach using Java.

Thanks

Mike.
 
J

Jan Thomä

I need to combine 3 number values into a 2 byte array.
The value bit sizes are:

value1 = 6 bits.
value2 = 6 bits.
value3 = 12 bits.

IIRC, two bytes are 16 bits. Your information is 24 bits, you would
probably need three bytes to fit your information in. So to do that

byte[] bytes = new byte[3];


1.st byte contains the 6 bits of value1 and two upper bits of value 2:

bytes[0] = (value1 << 2) & (value2 >> 4) & 0xFF;

2nd byte contains lower four bits of value2 and upper four bits of value
3. Third byte gets lower 8 bits of value3, i guess you get the idea...

That being said, the way i presented here is probably not the best
approach but it's the first that came to my mind :D

Kind regards,
Jan
 
M

mikew01

As Jan has pointed out you cannot fit 24 bits into 16 bits.  You need
to rethink the specification.  Why are you trying to compress data
like this?  What other ways are there to compress the data?

Trying to do a lot of bit-twiddling will slow down your application.

rossum

Sorry there is a typo in the first post, value3 is 4 bits not 12
It's not up to me how the data is packaged unfortunately, I am dealing
with a platform that has very limited resources so every bit counts.

Thanks

Mike
 
E

Eric Sosman

Sorry there is a typo in the first post, value3 is 4 bits not 12
It's not up to me how the data is packaged unfortunately, I am dealing
with a platform that has very limited resources so every bit counts.

Sixteen bits fit in two eight-bit bytes quite easily. Just
choose a suitable arrangement and do some shifting, for example:

int tmp = value1 | (value2 << 6) | (value3 << 12);
byte[] array = new byte[2];
array[0] = (byte)tmp;
array[1] = (byte)(tmp >> 8);

When picking them apart again you need to be just a little bit
careful to make sure byte's sign bit doesn't "smear" the result:

byte[] array = new byte[] { ...blah..., ...blah... };
int tmp = (array[0] & 0xFF) | (array[1] << 8);
int value1 = tmp & 0x3F;
int value2 = (tmp >> 6) & 0x3F;
int value3 = (tmp >> 12) & 0xF;

Concerning your "every bit counts" concern, note that this
packing and unpacking is not free. It takes code, it takes a few
auxiliary variables and constants, and all these things take space.
This is only going to be worthwhile if you pack a large number of
these triples, enough so the savings of one byte per triple makes
up for the space wasted in getting them in and out.

Actually, "one byte per triple" may be overstating the savings.
Keep in mind that a Java array is a full-fledged object instance,
and Java uses some memory to maintain that, er, objectivity. How
much depends on the platform, but you can expect a byte[2] array to
take maybe twelve bytes of memory. So if you're packing a large
number of triples, you shouldn't pack each into its own byte[2] but
instead into adjacent pairs in a much bigger byte[N]. (That is,
one triple goes in [0] and [1], the next in [2] and [3], and so on.)
Or perhaps you could just pack them into a short instead of into two
bytes -- it depends what you plan to do with them after packing.

Anyhow, my point is that you shouldn't overlook the costs that
are associated with obtaining the savings. Don't drive fifty miles
to buy gasoline for two cents a gallon less than the local rate.
 
A

Arne Vajhøj

Sorry there is a typo in the first post, value3 is 4 bits not 12
It's not up to me how the data is packaged unfortunately, I am dealing
with a platform that has very limited resources so every bit counts.

Probably the most efficient is just to do the bit shifting and
masking as proposed by other.

If you are willing to spend a bit more memory and CPU for the
sake of cleaner code, then I have a little record package
to write and read native structures.

See demo below.

Arne

====================

import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
import dk.vajhoej.record.StructWriter;

@Struct
public class ThreeBitFields {
@StructField(n=0,type=FieldType.BIT,length=6)
private int value1;
@StructField(n=1,type=FieldType.BIT,length=6)
private int value2;
@StructField(n=2,type=FieldType.BIT,length=4)
private int value3;
public int getValue1() {
return value1;
}
public void setValue1(int value1) {
this.value1 = value1;
}
public int getValue2() {
return value2;
}
public void setValue2(int value2) {
this.value2 = value2;
}
public int getValue3() {
return value3;
}
public void setValue3(int value3) {
this.value3 = value3;
}
public static void main(String[] args) throws Exception {
ThreeBitFields o = new ThreeBitFields();
o.setValue1(1);
o.setValue2(3);
o.setValue3(5);
StructWriter sw = new StructWriter();
sw.write(o);
byte[] b = sw.getBytes();
for(int i = 0; i < b.length; i++) {
System.out.printf("%02X", b);
}
System.out.println();
}
}
 
M

mikew01

Sorry there is a typo in the first post, value3 is 4 bits not 12
It's not up to me how the data is packaged unfortunately, I am dealing
with a platform that has very limited resources so every bit counts.

Probably the most efficient is just to do the bit shifting and
masking as proposed by other.

If you are willing to spend a bit more memory and CPU for the
sake of cleaner code, then I have a little record package
to write and read native structures.

See demo below.

Arne

====================

import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
import dk.vajhoej.record.StructWriter;

@Struct
public class ThreeBitFields {
     @StructField(n=0,type=FieldType.BIT,length=6)
     private int value1;
     @StructField(n=1,type=FieldType.BIT,length=6)
     private int value2;
     @StructField(n=2,type=FieldType.BIT,length=4)
     private int value3;
     public int getValue1() {
         return value1;
     }
     public void setValue1(int value1) {
         this.value1 = value1;
     }
     public int getValue2() {
         return value2;
     }
     public void setValue2(int value2) {
         this.value2 = value2;
     }
     public int getValue3() {
         return value3;
     }
     public void setValue3(int value3) {
         this.value3 = value3;
     }
     public static void main(String[] args) throws Exception {
         ThreeBitFields o = new ThreeBitFields();
         o.setValue1(1);
         o.setValue2(3);
         o.setValue3(5);
         StructWriter sw = new StructWriter();
         sw.write(o);
         byte[] b = sw.getBytes();
         for(int i = 0; i < b.length; i++) {
             System.out.printf("%02X", b);
         }
         System.out.println();
     }

}


All, thanks for your advice.
Arne, your demo looks interesting, would you mind sharing the other
classes involved with me? namely:

dk.vajhoej.record.FieldType;
dk.vajhoej.record.Struct;
dk.vajhoej.record.StructField;
dk.vajhoej.record.StructWriter;


Thanks

Mike.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top