将二进制数据转换为有符号整数

5 投票
6 回答
6697 浏览
提问于 2025-04-17 04:34

我读取了一个二进制文件,得到了一个字符数组。当我把两个字节转换成一个整数时,我用的是 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。

6 个回答

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

一般来说,当你使用结构体(struct)时,你的格式字符串应该以某种对齐方式的标识符开始。这个默认的对齐方式在不同的机器上可能会有所不同。

所以,正确的结果是

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

-2在大端(big endian)表示法中的样子是:

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

你可以很简单地通过加上2来验证这个结果,最后会得到0。

2

-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

撰写回答