Reputation: 854
I receive datas, from a RS422 communication, in a byte tab (byte[]
).
Some of my data are in two's complement binary with the following rules :
Significant bits Two's complement
MSB LSB
00000000 0
00000001 + LSB
01111111 + MSB - LSB
10000000 - MSB
10000001 - MSB + LSB
11111111 - LSB
To convert byte[] data to decimal, in pure binary, I use the following code :
Byte b05 = new Byte(new Integer(0x7A).byteValue()); // I use those bytes for my test
Byte b06 = new Byte(new Integer(0x00).byteValue());
Byte[] byteTabDay = new Byte[2] ;
byteTabDay[0] = b05 ;
byteTabDay[1] = b06 ;
int valueDay = byteTabDay[1] << 8 | byteTabDay[0] ;
System.out.println("day :" + valueDay); // print 122
But I don't know how to convert, like previously, byte[] that contain two's complement binary data like that:
Byte b20 = new Byte(new Integer(0x00).byteValue());
Byte b21 = new Byte(new Integer(0xFF).byteValue());
Byte b22 = new Byte(new Integer(0x3C).byteValue());
Those data contain, in theory, the value (more or less) : 1176
So I need help cause I don't understand how I can convert my byte data which contains two's complement binary to decimal.
Upvotes: 1
Views: 10707
Reputation: 109547
Two's complement binary is the standard for representing numbers with negative numbers included.
For three-bit numbers:
Base 2 (One's Two's
complement) complement
000 = 0
001 = 1
010 = 2
011 = 3
100 = 4 -3 -4
101 = 5 -2 -3
110 = 6 -1 -2
111 = 7 -0 -1
Java assumes two's complement: the most significant bit being 1 means negative.. Also in java byte, short, int, long are signed. As an aside, you used the Object wrappers for the primitive types. Primitive types are more immediate.
byte b05 = (byte) 0x7A;
byte b06 = (byte) 0x00; // MSB, positive as < 0x80
nyte[] byteTabDay = new byte[2];
byteTabDay[0] = b05;
byteTabDay[1] = b06;
int valueDay = ((int) byteTabDay[1]) << 8) | (0xFF & byteTabDay[0]);
System.out.println("day :" + valueDay); // print 122
What one has to do: keep the sign extension of the most significant byte, but for other bytes keep them to 8 bits by masking them with 0xFF.
Upvotes: 2
Reputation: 298143
The easiest way to convert an arbitrary byte array containing a two’s complement value to a decimal representation is new BigInteger(bytearray).toString()
.
This, however, expects the data to be in the big endian byte order. If the data is in little endian order as it seems in your question, you have to reverse it for the use with BigInteger
.
byte[] bytearray={ 0x7A, 0x00 };
ByteBuffer b=ByteBuffer.allocate(bytearray.length);
for(int ix=bytearray.length; ix>0; ) b.put(bytearray[--ix]);
System.out.println(new BigInteger(b.array()).toString()); // print 122
If the length of the array matches a standard primitive value type size, you can use ByteBuffer
to get the value directly:
byte[] bytearray={ 0x7A, 0x00 };
System.out.println(ByteBuffer.wrap(bytearray)
.order(ByteOrder.LITTLE_ENDIAN).getShort()); // print 122
However, don’t expect the value 1176.61254
as a result. That’s impossible.
If you think that this is the encoded value you will have to adapt your specification. There is no standard three-byte format for floating point values.
Upvotes: 1