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.