0

I'm trying to convert date of birth (three ints) to byte and convert it back but I'm having an issue. I have to convert it by using bit operations and send data over multicast server and receive it and change back to int. Server works fine, but bit operations are hard for me. What's the matter with the code:

Convert:

      int D=12; 
      int M=9; 
      int Y=1983;
      short DMY=0; 
      DMY = (short)(DMY | (D << 19));
      DMY = (short)(DMY | (M << 15));
      DMY = (short)(DMY | Y); 
      byte[] data = new byte[3];
      data[0] = (byte)(DMY >>> 8 );
      data[1] = (byte)(DMY >>> 16 );
      data[2] = (byte)(DMY & 0xffff);

Convert back:

           byte[] rec_data = new byte[3];
           rec_data = dp.getData();
           short Rec_dmy;


           Rec_dmy = (short)(rec_data[0] & 0xff);
           Rec_dmy = (short) (Rec_dmy << 8);
           Rec_dmy = (short)(Rec_dmy | (rec_data[1] & 0xff));
           Rec_dmy = (short) (Rec_dmy << 8);
           Rec_dmy = (short)(Rec_dmy | (rec_data[2] & 0xffff));

           byte tmp = (byte) ((Rec_dmy  >>> 19) & 0x1F);
           byte tmp2 = (byte) ((Rec_dmy >>> 15) & 0x1FF);
           byte tmp3 = (byte) (Rec_dmy & 0x7F);       

            System.out.println(tmp);
            System.out.println(tmp2);
            System.out.println(tmp3);

Println gives following answer: 31 -1 63

It's not near original 12 9 1983

obataku
  • 29,212
  • 3
  • 44
  • 57
user1528100
  • 49
  • 2
  • 5

3 Answers3

3

Shorts can only hold 16 bits; you are trying to pack more than that (e.g. shifting day left by 19, which will result in an all-zero value once casted to a short). You need to use an int or a long to hold all the fields.

Indeed, you've got several things going on with the bit operations that aren't right.

My suggestion would be to ditch the bit operations and just send the day, month and year as separate fields: one byte for each of the day and month, and two (a short) for the year. That takes 4 bytes (only one extra byte) but requires a lot less fiddling to get right.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • A shift by `19` does not shift it out of the `short` entirely, since the expression type is `int`, and the shift distance is computed to be `19 & 31`. It loses the data only when casting back to `short`. – obataku Aug 25 '12 at 05:30
  • I guess I meant that in the sense of getting shifted out of the short's viable range (i.e. shifting so that the low 16 bits are zero). I'll clarify what I mean. – nneonneo Aug 25 '12 at 05:33
1

Its not easy, but you have to work systematically to ensure your operations don't a) lose information b) decode the reverse of how you have encoded.

int D = 12;
int M = 9;
int Y = 1983;
int DMY = (D << 19) | (M << 15) | Y;
byte[] data = new byte[3];
data[0] = (byte) (DMY >>> 16);
data[1] = (byte) (DMY >>> 8);
data[2] = (byte) DMY;

int DMY2 = ((data[0]&0xFF) << 16) | ((data[1]&0xFF) << 8) | (data[2]&0xFF);
int D2 = DMY2 >>> 19;          // no mask required
int M2 = (DMY2 >>> 15) & 0x0F; // 4 bits mask
int Y2 = DMY2 & 0x7FFF;        // 15 bit mask
System.out.println(D2 + "/" + M2 + "/" + Y2);

prints

12/9/1983
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

First, you need at least 14 bits to represent the year with max value 9999 because of 2^14 > 9999 && 2 ^ 13 < 9999. And the least number of bits for month is 4(12 at max), day is 5(31 at max). So you can use a short int(16 bits) to represent year and byte (8 bits) for each day and month. So you get a 32-bits int.

public int encoded(short year, byte month, byte day){
    int data =0;
    data = year & 0xFFFF;
    data =(data << 8)|(month & 0xFF)
    data =(data << 8)|(day & 0xFF)
    return data;
}

public void decode(int data){
    int day = data & 0xFF;
    int month = (data >> 8) & 0xFF;
    int year = (data >> 16) & 0xFFFF;
}
George
  • 4,029
  • 2
  • 22
  • 26
  • Except he _is_ using 14 bits for the year, 4 for the month and 5 for the day! His problem is that the bit manipulation isn't correct. – nneonneo Aug 25 '12 at 05:46
  • i changed shorts to long but still no correct answer. nneonneo what's the problem with my bit operations? – user1528100 Aug 25 '12 at 07:04
  • @user1528100, you used 13 bits for day, 4 bits for month, and the left 15 bits for year. First of all, short for DMY is not enough, you should use at least int. Second you should stop explicitly converting int to short. After that, you then convert the the DMY to three bytes array which may be enough, and even worse, the way you convert DMY to byte array make you lost your data. That's the problem. – George Aug 25 '12 at 07:58