简体   繁体   中英

Converting 5 bytes to an integer

I have some weird data that's stored in 5 bytes and I need to be able to convert it to an int to be able to manipulate it easier. I have some Python code (that was provided to me) that does this already, but I need to be able to have a solution in Java. I think my problem is now Python and Java differ in the way they store bytes.

Python (98% sure this works correctly):

def bin5(b,k):
  """ Returns binary integer from bytes k,k+1,...,k+4 in b."""
  b0 = b[k  ]
  b1 = b[k+1]
  b2 = b[k+2]
  b3 = b[k+3]
  b4 = b[k+4]
  if b0<0: b0 += 256
  if b1<0: b1 += 256
  if b2<0: b2 += 256
  if b3<0: b3 += 256
  if b4<0: b4 += 256
  return b0*65536.0+b1*256.0+b2+b3/256.0+b4/65536.0

Java attempt:

  // Returns binary integer from bytes k,k+1,...,k+4 in b.
  private static int bin5(byte[] b, int k) {
    byte b0 = b[k];
    byte b1 = b[k + 1];
    byte b2 = b[k + 2];
    byte b3 = b[k + 3];
    byte b4 = b[k + 4];
    return (int)(b0 * 65536.0 + b1 * 256.0 + b2 + b3 / 256.0 + b4 / 65536.0);
  }

I'm certain the problem is in the last return statement of the Java code. Also, it will work for some byte arrays, but not for others. I can't find a reason for this behavior.

EDIT: Example: If the Python code reads the bytes: 0 11 -72 0 0 for b0 thru b5 respectfully, it will change the -72 to 184 and then calculate the value 3000.0 based on the equation above. Based on the survey/data parameters, this value is correct.

My intuition says that the python code IS faulty for some values. One such value is when it reads a values 0 -127 -66 0 0 (b0 thru b5 respectfully) which turns into: 0 129 190 0 0 and then the value 33214 is output by the conversion. This is impossible based on the survey/data parameters. BUT there is a possibility that this could be a faulty data point.

EDIT 2: 0 13 9 0 0 should return 3337 (and does in the python code). However under Java, it returns 3593.

You could do

private static double bin5(byte[] b, int k) {
    int b0 = b[k] & 0xFF;     // treat as unsigned byte
    int b1 = b[k + 1] & 0xFF;
    int b2 = b[k + 2] & 0xFF;
    int b3 = b[k + 3] & 0xFF;
    int b4 = b[k + 4] & 0xFF;
    return (b0 * 65536 + b1 * 256 + b2 + b3 / 256.0 + b4 / 65536.0);
}

As powers of 2 can be represented exactly with double you won't get any rounding error.

This code is strange; it does not return an integer at all but a float...

Anyway, the Java equivalent of the python code is something like this (note: NO bounds checking is done at all ):

private static double bin5(final byte[] b, final int k)
{
    final ByteBuffer buf = ByteBuffer.allocate(8);
    buf.position(3);
    buf.put(b, k, 5);
    buf.rewind();
    final long l = buf.getLong();
    return (double) l / 65536.0;
}

EDIT: if the last two elements of the byte array at offset k are always 0 (which it looks like they are) then you can replace from buf.rewind() onwards with:

buf.position(2);
return (double) buf.getInt();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM