Say I read these bytes: "6F D4 06 40" from an input device. The number is a longitude reading in MilliArcSeconds format. The top bit (0x80000000) is basically always zero and is ignored for this question.
I can easily convert the bytes to an unsigned integer: 1876166208
But how do I convert that unsigned value into its final form of 31-bit signed-integer?
So far all I've come up with is:
So I can tell if it's a negative number, but in order to know what value the negative number is, I have to do something with the remaining bits - a one's compliment? How do I do that in Java?
Another way to put the question is, how do I convert an unsigned integer into a 31-bit signed integer in Java?
Thank you!
The answer depends on what the lower 31 bits of your input are meant to represent.
int input = 0x6FD40640 & 0x7FFFFFFF; //strip top bit; only here for clarity
Unsigned input: 0x6FD40640 == 1876166208
A two's complement integer is one where -1 has all bits set, and lower negatives number count down from there. The first bit still acts as a sign bit.
1000 -> -8
1001 -> -7
...
1110 -> -2
1111 -> -1
0000 -> 0
0001 -> 1
If the lower 31 bits represent a two's complement integer, then I think you should just be able to do this:
input = (input << 1) >> 1;
That's because Java stores integers in two's complement internally: all we do is shift left and then shift back right (signed) so that the sign bit is picked up and the integer goes from 31 bits to 32 bits.
A one's complement number representation is one where the first bit is a dedicated sign bit, and the remaining bits represent the magnitude. The lower bits of -100 will be the same as the lower bits of 100:
1111 -> -7
1110 -> -6
...
1001 -> -1
1000 -> -0 (anomoly)
0000 -> 0
0001 -> 1
If the lower 31 bits represent a one's complement integer (that is, a sign bit followed by 30 bits representing an unsigned magnitude), then you need to convert it into two's complement so that Java extracts the value properly. To do this you just need to extract the lower 30 bits and multiply by -1:
if ( input & 0x40000000 ) {
input = (input & 0x3FFFFFFF) * -1;
}
You said in the question's comments that after converting to degrees (dividing by 3600000) you get around -75.36. When I divide -271317440 by 3600000 I get -75.36595555555556, so I'm guessing your input format is two's complement, so my first and original answer was correct.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With