Reputation: 191
I read a binary file and get an array with characters. When converting two bytes to an integer I do 256*ord(p1) + ord(p0)
. It works fine for positive integers but when I get a negative number it doesn't work. I know there is something with the first bit in the most significant byte but with no success.
I also understand there is something called struct
and after reading I ended up with the following code
import struct
p1 = chr(231)
p0 = chr(174)
a = struct.unpack('h',p0+p1)
print str(a)
a
becomes -6226 and if I swap p0
and p1
I get -20761.
a
should have been -2
Upvotes: 5
Views: 6873
Reputation: 308158
Your original equation will work fine if you use masking to take off the extra 1
bits in a negative number:
256*(ord(p0) & 0xff) + (ord(p1) & 0xff)
Edit: I think I might have misunderstood your question. You're trying to convert two positive byte values into a negative integer? This should work:
a = 256*ord(p0) + ord(p1)
if a > 32767: # 0x7fff
a -= 65536 # 0x10000
Upvotes: 0
Reputation:
If you are converting values from a file that is large, use the array module.
For a file, know that it is the endianess of the file format that matters. Not the endianess of the machine that either wrote it or is reading it.
Alex Martelli, of course, has the definitive answer.
Upvotes: 0
Reputation: 177665
-2 is not correct for the values you have specified, and byte order matters. struct
uses >
for big-endian (most-significant byte first) and <
for little-endian (least-significant byte first):
>>> import struct
>>> struct.pack('>h',-2)
'\xff\xfe'
>>> struct.pack('<h',-2)
'\xfe\xff'
>>> p1=chr(254) # 0xFE
>>> p0=chr(255) # 0xFF
>>> struct.unpack('<h',p1+p0)[0]
-2
>>> struct.unpack('>h',p0+p1)[0]
-2
Upvotes: 2
Reputation: 184191
For the record, you can do it without struct
. Your original equation can be used, but if the result is greater than 32767, subtract 65536. (Or if the high-order byte is greater than 127, which is the same thing.) Look up two's complement, which is how all modern computers represent negative integers.
p1 = chr(231)
p0 = chr(174)
a = 256 * ord(p1) + ord(p0) - (65536 if ord(p1) > 127 else 0)
This gets you the correct answer of -6226. (The correct answer is not -2.)
Upvotes: 0
Reputation: 4214
With the first method (256*ord(p1) + ord(p0)
), you could check to see if the first bit is 1 with if p1 & 0x80 > 0
. If so then you'd use p1 & 0x7f
instead of p1
and then negate the end result.
Upvotes: 0
Reputation: 287835
Generally, when using struct, your format string should start with one of the alignment specifiers. The default, native one differs from machine to machine.
Therefore, the correct result is
>>> struct.unpack('!h',p0+p1)[0]
-20761
The representation of -2 in big endian is:
1111 1111 1111 1110 # binary
255 254 # decimal bytes
f f f e # hexadecimal bytes
You can easily verify that by adding two, which results in 0.
Upvotes: 1