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

Posted

技术标签:

【中文标题】从“无符号”字节流中读取 32 位有符号值【英文标题】:Read 32-bit signed value from an "unsigned" bytestream 【发布时间】:2012-02-09 18:09:07 【问题描述】:

我想从一个文件中提取数据,该文件的信息存储在大端并且总是无符号。从 unsigned intint"cast" 如何影响实际的十进制值?我是否正确,最左边的位决定了该值是正数还是负数?

我想用 python 解析那个文件格式,读取和无符号值很容易:

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

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


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

【问题讨论】:

我想你想要结构模块。 以前用过,但没有提供正确的结果。嗯,等等,我想我需要告诉它字节流有什么字节序? xD @jterrace 伙计,我不知道我可以告诉它有关字节序的信息。谢谢 jterrace。但是,我仍然会对解决方案感兴趣。 :) 最高有效位确实定义了数字的符号。我知道您所说的“最左端”是什么意思,但是在谈论大端和小端时会让人感到困惑。 【参考方案1】:

我会使用struct。

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”。

编辑

必须查看另一个 *** 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)

【讨论】:

感谢您的信息,不知道。 :) 但是,我仍然对硬编码版本感兴趣。【参考方案2】:

我会使用struct module's 打包和解包方法。

有关示例,请参阅 Endianness of integers in Python。

【讨论】:

【参考方案3】:

toS32(bits) 的无条件版本可能类似于:

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

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

【讨论】:

以上是关于从“无符号”字节流中读取 32 位有符号值的主要内容,如果未能解决你的问题,请参考以下文章

Scala 常用整理

Scala 常用整理

Scala 常用整理

嵌入式:ARM存储器组织协处理器及片上总线

将 8 位无符号 PCM 转换为 8 位有符号 PCM

句柄Windows数据类型