繁体   English   中英

在 Python 中将二进制转换为带符号的小端 16 位 integer

[英]Convert binary to signed, little endian 16bit integer in Python

尝试将二进制列表转换为有符号的 16 位小端 integer

input_data = [['1100110111111011','1101111011111111','0010101000000011'],['1100111111111011','1101100111111111','0010110100000011']]
Desired Output =[[-1074, -34, 810],[-1703, -39, 813]]

这就是我到目前为止所得到的。 它改编自: Hex string to signed int in Python 3.2? , 在 python 中从 HEX 转换为 SIGNED DEC

results = []
for i in input_data:
   hex_convert = [hex(int(x,2)) for x in i]
   convert = [int(y[4:6] + y[2:4], 16) for y in hex_convert]
   results.append(convert)
print (results)
output: [[64461, 65502, 810], [64463, 65497, 813]]

这很好用,但上面是无符号整数。 我需要能够处理负值的有符号整数。 然后我尝试了另一种方法:

results_2 = []
for i in input_data:
   hex_convert = [hex(int(x,2)) for x in i]
   to_bytes = [bytes(j, 'utf-8') for j in hex_convert]
   split_bits = [int(k, 16) for k in to_bytes]
   convert_2 = [int.from_bytes(b, byteorder = 'little', signed = True) for b in to_bytes]
   results_2.append(convert_2)
print (results_2)
Output: [[108191910426672, 112589973780528, 56282882144304], [108191943981104, 112589235583024, 56282932475952]]

这个结果比第一个更疯狂。 我知道我的方法是错误的,而且我一直无法理解二进制转换等并没有帮助,但我觉得我走在正确的道路上:

(b, byteorder = 'little', signed = True)

但无法弄清楚我错在哪里。 任何帮助解释这个概念将不胜感激。

这个结果比第一个更疯狂。 我知道我的方法是错误的......但无法弄清楚我错在哪里。

问题在于转换字节。 让我们一步一步看:

int(x, 2)

美好的; 我们将字符串视为 integer 值的 base-2 表示,并得到 integer。 唯一的问题是它是a)无符号和b)大端。

hex(int(x,2))

这样做是创建 integer 的字符串表示形式,以 16 为底,前缀为0x 值得注意的是,我们需要每个字节有两个文本字符。 这已经走错路了。

您可能已经考虑过使用十六进制,因为您已经在字符串表示中看到了\xAB样式的转义。 这是完全不同的事情。 字符串'\xAB'包含一个字符。 字符串'0xAB'包含四个。

从那里开始,其他一切仍然是无稽之谈。 使用文本编码转换为bytes仅意味着文本字符0被替换为字节值 48(因为在 UTF-8 中,它使用具有该值的单个字节进行编码)。 对于此数据,我们使用 UTF-8 得到与假设纯 ASCII 相同的结果(因为 UTF-8 是“ASCII 透明”并且文本中没有非 ASCII 字符)。


那么我们该怎么做呢?

我们要将第一步中的 integer 转换为用于表示它的字节。 正如有一个.from_bytes class 方法允许我们从底层字节创建一个 integer 一样,有一个实例方法允许我们获取代表 Z157DB7DF530023575515D366C9B672 的字节。

因此,我们使用.to_bytes ,指定当我们从二进制字符串创建int时假定的长度、符号和字节序——这为我们提供了与该字符串对应的字节。 然后,我们从这些字节重新创建 integer,除了现在指定正确的符号和字节序。 .to_bytes让我们指定长度的原因是因为 integer 没有特定的长度 - 表示它需要最少的字节数,但您可以使用任意多的字节数。 (如果您想处理有符号值,这一点尤其重要,因为它会自动进行符号扩展。)

因此:

for i in input_data:
    values = [int(x,2) for x in i]
    as_bytes = [x.to_bytes(2, byteorder='big', signed=False) for x in values]
    reinterpreted = [int.from_bytes(x, byteorder='little', signed=True) for x in as_bytes]
    results_2.append(reinterpreted)

但是让我们稍微改进一下代码的组织。 我将首先制作一个 function 来处理单个 integer 值,然后我们可以使用推导来处理列表。 事实上,我们可以对嵌套列表使用嵌套推导。

def as_signed_little(binary_str):
    # This time, taking advantage of positional args and default values.
    as_bytes = int(binary_str, 2).to_bytes(2, 'big')
    return int.from_bytes(as_bytes, 'little', signed=True)

# And now we can do:
results_2 = [[as_signed_little(x) for x in i] for i in input_data]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM