2011-10-18 180 views
4

我读取一个二进制文件并获取一个包含字符的数组。当将两个字节转换为整数时,我做256*ord(p1) + ord(p0)。它对正整数正常工作,但当我得到一个负数时它不起作用。我知道在最重要的字节中有第一个字节,但没有成功。将二进制数据转换为有符号整数

我也知道有个东西叫struct和阅读后,我结束了与下面的代码

import struct 

p1 = chr(231) 
p0 = chr(174) 

a = struct.unpack('h',p0+p1) 

print str(a) 

a变为-6226,如果我换p0p1我得到-20761。

a应该是-2

回答

0

与第一种方法(256*ord(p1) + ord(p0)),你可以检查,看是否第一位是1 if p1 & 0x80 > 0。如果是这样,那么你会使用p1 & 0x7f而不是p1,然后否定最终结果。

1

通常,使用struct时,您的格式字符串应该以alignment specifiers之一开头。本机的默认设置因机器而异。

因此,正确的结果是

>>> struct.unpack('!h',p0+p1)[0] 
-20761 

在大endian的-2表示为:

1111 1111 1111 1110 # binary 
    255  254 # decimal bytes 
    f f f e # hexadecimal bytes 

可以很容易地确认通过添加两个,这将导致0

0

如果您使用掩码来取消负数中多余的1位,您的原始公式将正常工作:

256*(ord(p0) & 0xff) + (ord(p1) & 0xff) 

编辑:我想我可能误解了你的问题。你试图将两个正值字节值转换为一个负整数?这应该工作:

a = 256*ord(p0) + ord(p1) 
if a > 32767: # 0x7fff 
    a -= 65536 # 0x10000 
+1

由于这些已经是8位数量,屏蔽掉较低的8位不会做任何事情。 – kindall

+0

要屏蔽符号位,您可以使用'&0x7F',否? – 2011-10-18 19:12:18

+0

@ kindall,原始问题谈到负数。负数是符号扩展的,所以高位包含“1”而不是“0”,因此掩盖它们变得必要。我仍然不确定'ord'如何返回一个负数。 –

0

备案,你可以做到这一点,没有struct。你可以使用原始公式,但是如果结果大于32767,则减去65536.(或者如果高位字节大于127,这是相同的事情。)查找二进制补码,这就是所有现代计算机代表负整数。

p1 = chr(231) 
p0 = chr(174) 

a = 256 * ord(p1) + ord(p0) - (65536 if ord(p1) > 127 else 0) 

这会让你得到-6226的正确答案。 (正确答案不是-2.

1

-2对于您指定的值是不正确的,并且字节顺序很重要。 struct使用>为大端(最显著字节在前)和<为小端(最低显著字节在前):

>>> 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 
0

如果从一个文件,是大转换值,可以使用array模块。

对于一个文件,要知道它是文件格式的重要性。不是机器的永久性,不是写它就是读它。

Alex Martelli当然有the definitive answer

相关问题