Reputation: 307
I have some binary data from my weather station I need to convert to decimal. I have to combine 2 bytes then right shift by 4. Currently I do this as follows:
byte1 = 251
byte2 = 74
result = (byte1 * 256 + byte2) >> 4
print(result)
This works fine when the incoming data is positive, but when it's negative it's in a 2's complement format and the above code doesn't handle it properly. The result is 4020, but I want -76.
How do I get this to handle 2's complement properly?
Upvotes: 0
Views: 70
Reputation: 346
byte1 = 251
byte2 = 74
byte_mask = ~0xFFFF
if (byte1>=128):
result = ( ((byte1 << 8) + byte2) | byte_mask ) >> 4
else:
result = ((byte1 << 8) + byte2) >> 4
We all know what 2's complement is... if the left-most bit is a 1, the number is a negative and we should perform 2's complement to get the number. That's the easy part. The hard part is that you're working in Python. Python's numbering is a blessing and a curse because Python's numbers are INFINITE (roughly speaking). We need to somehow set all of the leftmost bits of an infinite number to 1, so you can do:
byte_mask = ~0xFFFF
Now byte_mask is 1111 1111 1111 1111 1111 1111 ..... 0000 0000 0000 0000
If your incoming byte1 is greater than 128 (and thus a negative number), we just OR your byte1byte2 number, giving the intermediate result:
1111 1111 1111 1111 ..... 1111 1011 0100 1010
Which is clearly much closer to what we want. Then shift right 4. (When we shift right, the left-most 4 digits will be filled with 1 of course):
1111 1111 1111 1111 ..... 1111 1111 1011 0100
Which is, in decimal, what you want: -76
Upvotes: 1