使用 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'
>>>