使用 Python 来操作 31 位
Using Python to manipulate 31-bits
我有一个规范,其中概述了应如何通过串行方式发送指令。
目前我正在制作将通过连接的数据包。
数据包的一段,需要一个32位(4字节)的二进制数。
前 31 位是 'data',最后一位只是一个标志。
所以,数据中可以容纳的最大十进制数是:2147483647 (2^31)。数据永远不会比这更大,酷!
我的问题是如何将数据编码为 31 位二进制,然后设置最后一位以启用标志?
假设我的数据是 7AAAAAAA
将其转换为 31 位二进制然后在末尾添加 1 或 0 的理想方法是什么?
编辑 - 我正在使用 Python 3.4
我唯一想到的就是对字符串的操作
假设我们有两个变量:
>>> data = '7AAAAAAA'
>>> flag = '1'
将数据十六进制转换为数字
>>> num = int(data, 16)
>>> num
2058005162
将数字转换为字符串二进制表示:
>>> bin_num = bin(num)
>>> bin_num
'0b1111010101010101010101010101010'
将标志附加到末尾
>>> bin_num += flag
>>> bin_num
'0b11110101010101010101010101010101'
评估字符串以获取数字并转换回十六进制或您需要的任何内容:
>>> eval(bin_num)
4116010325
#edit1
为了将值扩展到 4 字节,您可以使用:
>>> final_val = eval(bin_num)
>>> int.to_bytes(final_val, 4, 'big')
b'\xf5UUU'
#edit2
def convert(data, flag):
with_flag = eval(bin(int(data, 16)) + flag)
return int.to_bytes(with_flag, 4, 'big')
def unconvert(byte_data):
bin_str = bin(int.from_bytes(byte_data, 'big'))
flag = bin_str[-1]
data = bin_str[:-1]
return (hex(eval(data)), flag)
我认为你可以使用二进制移位将你的标志添加到一个数字中:
a = 0x7AAAAAAA # 2058005162 = 0b1111010101010101010101010101010
f = 1 # 1 = 0b1
packet = a + (f << 31) # a + 0b10000000000000000000000000000000
bin(packet) # 0b11111010101010101010101010101010
要解压缩,您可以使用掩码和二进制文件并像这样:
mask = (1 << 31) - 1 # 2147483647 = 0b1111111111111111111111111111111
a = packet & mask # 2058005162 = 0b1111010101010101010101010101010
f = packet >> 31 # 1 = 0b1
看看这是否有效,类似于其他答案,但考虑了原始位长度。
定义最终位数
>>> bits = 16
以字节文字开始
>>> a = b'10'
转换为 int
>>> b = int(a, base = 16)
左移到需要的位长
>>> shift = bits - b.bit_length()
>>> c = b << shift
添加标志
>>> d = c | 1
>>>
>>> a
b'10'
>>> b
16
>>> c
32768
>>> d
32769
>>> bin(b)
'0b10000'
>>> bin(c)
'0b1000000000000000'
>>> bin(d)
'0b1000000000000001'
>>>
我有一个规范,其中概述了应如何通过串行方式发送指令。
目前我正在制作将通过连接的数据包。
数据包的一段,需要一个32位(4字节)的二进制数。 前 31 位是 'data',最后一位只是一个标志。
所以,数据中可以容纳的最大十进制数是:2147483647 (2^31)。数据永远不会比这更大,酷!
我的问题是如何将数据编码为 31 位二进制,然后设置最后一位以启用标志?
假设我的数据是 7AAAAAAA
将其转换为 31 位二进制然后在末尾添加 1 或 0 的理想方法是什么?
编辑 - 我正在使用 Python 3.4
我唯一想到的就是对字符串的操作
假设我们有两个变量:
>>> data = '7AAAAAAA'
>>> flag = '1'
将数据十六进制转换为数字
>>> num = int(data, 16)
>>> num
2058005162
将数字转换为字符串二进制表示:
>>> bin_num = bin(num)
>>> bin_num
'0b1111010101010101010101010101010'
将标志附加到末尾
>>> bin_num += flag
>>> bin_num
'0b11110101010101010101010101010101'
评估字符串以获取数字并转换回十六进制或您需要的任何内容:
>>> eval(bin_num)
4116010325
#edit1
为了将值扩展到 4 字节,您可以使用:
>>> final_val = eval(bin_num)
>>> int.to_bytes(final_val, 4, 'big')
b'\xf5UUU'
#edit2
def convert(data, flag):
with_flag = eval(bin(int(data, 16)) + flag)
return int.to_bytes(with_flag, 4, 'big')
def unconvert(byte_data):
bin_str = bin(int.from_bytes(byte_data, 'big'))
flag = bin_str[-1]
data = bin_str[:-1]
return (hex(eval(data)), flag)
我认为你可以使用二进制移位将你的标志添加到一个数字中:
a = 0x7AAAAAAA # 2058005162 = 0b1111010101010101010101010101010
f = 1 # 1 = 0b1
packet = a + (f << 31) # a + 0b10000000000000000000000000000000
bin(packet) # 0b11111010101010101010101010101010
要解压缩,您可以使用掩码和二进制文件并像这样:
mask = (1 << 31) - 1 # 2147483647 = 0b1111111111111111111111111111111
a = packet & mask # 2058005162 = 0b1111010101010101010101010101010
f = packet >> 31 # 1 = 0b1
看看这是否有效,类似于其他答案,但考虑了原始位长度。
定义最终位数
>>> bits = 16
以字节文字开始
>>> a = b'10'
转换为 int
>>> b = int(a, base = 16)
左移到需要的位长
>>> shift = bits - b.bit_length()
>>> c = b << shift
添加标志
>>> d = c | 1
>>>
>>> a
b'10'
>>> b
16
>>> c
32768
>>> d
32769
>>> bin(b)
'0b10000'
>>> bin(c)
'0b1000000000000000'
>>> bin(d)
'0b1000000000000001'
>>>