在 Python 中将二进制转换为带符号的小端 16 位整数
Convert binary to signed, little endian 16bit integer in Python
正在尝试将二进制列表转换为带符号的 16 位小端整数
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?,
Conversion from HEX to SIGNED DEC in python
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)
但无法找出我错在哪里。非常感谢任何解释这个概念的帮助。
This result is even more wild than the first. I know my approach is wrong... but can't work out where i'm wrong.
问题出在 到 字节的转换中。让我们一步步来看:
int(x, 2)
很好;我们将字符串视为整数值的 base-2 表示,并获取该整数。唯一的问题是它是 a) unsigned 和 b) big-endian。
hex(int(x,2))
这样做是创建整数的字符串表示形式,以 16 为基数,带有 0x
前缀。值得注意的是,我们想要的每个字节有两个文本字符。这已经走错路了。
您可能已经考虑过使用十六进制,因为您已经在字符串表示形式中看到 \xAB
样式转义。这是完全不同的事情。字符串 '\xAB'
包含一个字符。字符串 '0xAB'
包含四个。
从那里开始,其他一切仍然是废话。使用文本编码转换为 bytes
仅意味着文本字符 0
被替换为字节值 48(因为在 UTF-8 中它是用具有该值的单个字节编码的)。对于此数据,我们使用 UTF-8 得到的结果与我们假设纯 ASCII 得到的结果相同(因为 UTF-8 是“ASCII 透明的”并且文本中没有非 ASCII 字符)。
那么我们该怎么做呢?
我们想把第一步得到的整数转换成用来表示它的字节。正如有一个 .from_bytes
class 方法允许我们从底层字节创建一个整数一样,有一个实例方法允许我们获取代表整数的字节。
因此,我们使用 .to_bytes
,指定我们从二进制字符串创建 int
时假定的长度、符号和字节顺序 - 为我们提供与该字符串对应的字节。然后,我们从这些字节重新创建整数,除了现在指定正确的符号和字节顺序。 .to_bytes
让我们指定长度的原因是因为整数没有特定的长度——表示它需要最少的字节数,但您可以根据需要使用更多的字节数。 (如果你想处理带符号的值,这一点尤其重要,因为它会自动进行符号扩展。)
因此:
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)
但让我们稍微改进一下代码的组织。我将首先创建一个函数来处理单个整数值,然后我们可以使用理解来处理列表。事实上,我们可以对嵌套列表使用嵌套理解。
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]
正在尝试将二进制列表转换为带符号的 16 位小端整数
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?, Conversion from HEX to SIGNED DEC in python
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)
但无法找出我错在哪里。非常感谢任何解释这个概念的帮助。
This result is even more wild than the first. I know my approach is wrong... but can't work out where i'm wrong.
问题出在 到 字节的转换中。让我们一步步来看:
int(x, 2)
很好;我们将字符串视为整数值的 base-2 表示,并获取该整数。唯一的问题是它是 a) unsigned 和 b) big-endian。
hex(int(x,2))
这样做是创建整数的字符串表示形式,以 16 为基数,带有 0x
前缀。值得注意的是,我们想要的每个字节有两个文本字符。这已经走错路了。
您可能已经考虑过使用十六进制,因为您已经在字符串表示形式中看到 \xAB
样式转义。这是完全不同的事情。字符串 '\xAB'
包含一个字符。字符串 '0xAB'
包含四个。
从那里开始,其他一切仍然是废话。使用文本编码转换为 bytes
仅意味着文本字符 0
被替换为字节值 48(因为在 UTF-8 中它是用具有该值的单个字节编码的)。对于此数据,我们使用 UTF-8 得到的结果与我们假设纯 ASCII 得到的结果相同(因为 UTF-8 是“ASCII 透明的”并且文本中没有非 ASCII 字符)。
那么我们该怎么做呢?
我们想把第一步得到的整数转换成用来表示它的字节。正如有一个 .from_bytes
class 方法允许我们从底层字节创建一个整数一样,有一个实例方法允许我们获取代表整数的字节。
因此,我们使用 .to_bytes
,指定我们从二进制字符串创建 int
时假定的长度、符号和字节顺序 - 为我们提供与该字符串对应的字节。然后,我们从这些字节重新创建整数,除了现在指定正确的符号和字节顺序。 .to_bytes
让我们指定长度的原因是因为整数没有特定的长度——表示它需要最少的字节数,但您可以根据需要使用更多的字节数。 (如果你想处理带符号的值,这一点尤其重要,因为它会自动进行符号扩展。)
因此:
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)
但让我们稍微改进一下代码的组织。我将首先创建一个函数来处理单个整数值,然后我们可以使用理解来处理列表。事实上,我们可以对嵌套列表使用嵌套理解。
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]