从“无符号”字节流中读取32位有符号值

4

我希望从一个以大端方式存储信息且始终为无符号的文件中提取数据。从无符号整数到整数的"转换"如何影响实际十进制值?我是否正确,最左边的位决定值是正还是负数?

我想用Python解析该文件格式,并读取无符号值很容易:

def toU32(bits):
    return ord(bits[0]) << 24 | ord(bits[1]) << 16 | ord(bits[2]) << 8  | ord(bits[3])

但是相应的toS32函数会是什么样子呢?


感谢您提供有关struct模块的信息。但我仍然对我的实际问题的解决方案感兴趣。


我认为你想要使用struct模块。 - jterrace
以前用过它,但是没有得到正确的结果。等一下,我想我需要告诉它字节流的字节序是什么?xD - Niklas R
@jterrace 哥们,我不知道我可以告诉它关于字节序的事情..谢谢jterrace。然而,我仍然对解决方案感兴趣。 :) - Niklas R
最高位确实定义了数字的符号。我知道你所说的“最左边”,但在谈论大端和小端时可能会令人困惑。 - grieve
3个回答

9

我会使用结构体

import struct

def toU32(bits):
    return struct.unpack_from(">I", bits)[0]

def toS32(bits):
    return struct.unpack_from(">i", bits)[0]

格式字符串">I"表示从字符串位中读取大端无符号整数"I"。对于有符号整数,您可以使用">i"。
编辑
不得不查看另一个StackOverflow answer 来记住如何在Python中将无符号整数“转换”为有符号整数。虽然它更像是重新解释位,而不是转换。
import struct

def toU32(bits):
        return ord(bits[0]) << 24 | ord(bits[1]) << 16 | ord(bits[2]) << 8  | ord(bits[3])

def toS32(bits):
    candidate = toU32(bits);
    if (candidate >> 31): # is the sign bit set?
        return (-0x80000000 + (candidate & 0x7fffffff)) # "cast" it to signed
    return candidate


for x in range(-5,5):
    bits = struct.pack(">i", x)
    print toU32(bits)
    print toS32(bits)

谢谢提供这个信息,我之前不知道。:) 不过,我仍然对硬编码版本感兴趣。 - Niklas R

0

toS32(bits)的非条件版本可能是这样的:

def toS32(bits):
    decoded = toU32(bits)
    return -(decoded & 0x80000000) + (decoded & 0x7fffffff)

当然,您也可以预先计算其他位大小的掩码。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接