使用Python操作31位

使用Python操作31位,python,binary,hex,python-3.4,pyserial,Python,Binary,Hex,Python 3.4,Pyserial,我有一个规范,概述了如何通过串行通信发送指令 目前我正在制作通过连接的数据包 数据包的一段需要一个32位(4字节)的二进制数。 前31位为“数据”,最后一位仅为标志 因此,数据中可以容纳的最大十进制数是:2147483647(2^31)。数据永远不会比这更大,酷 我的问题是,如何将数据编码为31位二进制,然后设置最后一位以启用标志 假设我的数据是7aaaaaaaaa将其转换为31位二进制然后在末尾添加1或0的理想方式是什么 编辑-我正在使用Python 3.4我唯一想到的是对字符串的操作 假设我

我有一个规范,概述了如何通过串行通信发送指令

目前我正在制作通过连接的数据包

数据包的一段需要一个32位(4字节)的二进制数。 前31位为“数据”,最后一位仅为标志

因此,数据中可以容纳的最大十进制数是:2147483647(2^31)。数据永远不会比这更大,酷

我的问题是,如何将数据编码为31位二进制,然后设置最后一位以启用标志

假设我的数据是
7aaaaaaaaa
将其转换为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
a=0x7AAAAAAA#2058005162=0B1111010101010101010
f=1#1=0b1
数据包=a+(f 31#1=0b1

查看这是否有效,与其他答案类似,但考虑了原始位长度

定义最终位数

>>> bits = 16
从字节文本开始

>>> a = b'10'
转换为
int

>>> b = int(a, base = 16)
向左移位到所需的位长度

>>> shift = bits - b.bit_length()
>>> c = b << shift

查看
struct
模块和位修改操作符
|
。在这种情况下使用
struct
可能会有问题,因为您的数据编号不是4位整数。struct仅对完整字节进行操作。对于硬编码数据,您可以执行类似
(0x7aaaaabit在Python中摆弄可能有点棘手,因为我们没有无符号整数,而且我们的整数不是固定字节长度的。但是,仔细使用
struct
,这确实不是问题。这会起作用,我可以使用
binascii
对二进制数据进行编码。但是,如果数据只是
FF
binary表示不够大,可能是一种填充数据的方法,以始终使用31位二进制表示?您可以使用
int.to\u字节(最终的\u数字,4,'big')
来使用big-endian,并扩展到4字节或类似的
数据包=(a
>>> 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'
>>>