Python 将整数转换为半字节,`to_bytes()`?

Python 将整数转换为半字节,`to_bytes()`?,python,type-conversion,byte,bit,Python,Type Conversion,Byte,Bit,我有一个整数列表: var=[1,5,4,17231,89] 如果我想将其转换为字节列表,我可以执行以下操作: [(i).to_字节(1,byteorder='big')表示var中的i] 由于var中的每个值都小于256,因此每个整数可以容纳一个字节。但如果我有另一份清单,就说: var=[1,2,15,12] 这可以将一个整数放入半个字节,或者更准确地说,每个字节放入两个整数 如果可能的话,我如何指定将两个整数合并成一个字节,包括to和from 如下所示: var1=[1,5,4,17231

我有一个整数列表:

var=[1,5,4,17231,89]

如果我想将其转换为字节列表,我可以执行以下操作:

[(i).to_字节(1,byteorder='big')表示var中的i]

由于
var
中的每个值都小于256,因此每个整数可以容纳一个字节。但如果我有另一份清单,就说:

var=[1,2,15,12]

这可以将一个整数放入半个字节,或者更准确地说,每个字节放入两个整数

如果可能的话,我如何指定将两个整数合并成一个字节,包括to和from

如下所示:

var1=[1,5,4,17231,89]
var2=[1,2,15,12]
def foo(变量):
如果最大值(var)<2**4:
num_字节=0.5
elif最大值(var)<2**8:
num_字节=1
elif最大值(var)<2**16:
num_字节=2
如果num_bytes>=1:
对于var中的i,返回[(i).to_字节(num_字节,byteorder='big')],num_字节
elif num_bytes=0.5:
#将var转换为nybles列表
#将两个nybble合并为一个字节
#创建字节列表(长度为变量长度的一半)
#返回它和num_字节
def unfoo(变量,num_字节):
如果num_bytes>=1:
打印([int.from_字节(i,'big')表示变量中的i])
elif num_bytes=0.5:
#再次打印原始整数列表
我想把一个整数列表转换成一个字节列表,但是如果可以的话,将两个nybles转换成一个字节,然后再进行转换

预期结果是:

a,b=foo(var1)
unfoo(a,b)#prints[1,5,4,17231,89]
a、 b=foo(var2)
unfoo(a,b)#打印[1,2,15,12]
我不想要一个最小位数的列表来代表一个数字。注意
max(list)
:如果列表中的所有值都可以是8位,则将其调整为8位;如果所有值都可以是16位,则将其调整为16位;如果所有值都可以是Nyble,则将两个Nyble对组成一个字节列表


基本上,如果我有两个整数,每一个都可以放在一个nyble中,那么如何将它们连接到一个字节中呢?如果我知道需要将字节拆分为两个,如何进行拆分?我可以假定原始列表可以被2整除。

您需要计算出一个字节可以容纳多少个数字。然后,您需要按正确的数量移动每个数字,并创建一个包含组合数字的新列表。假设你可以在一个字节中放入两个数字,你会得到
new_number=(old_num1我写了两个简单的函数,一个将两个数字打包成一个字节(显然数字必须放入半个字节),另一个将它们解包:

def concatToByte(num1,num2):
nybbleSize=2**4
如果num1>=NybleSize或num2>=NybleSize:
raise VALUERROR(“参数必须适合nybble大小”)
返回(num1>0x4
num2=(byteAsInt&0x0F)
返回num1,num2
然后您可以按如下方式使用它:

inNum1=5#十六进制:0x05
inNum2=12#十六进制:0x0c
byte=concatToByte(inNum1,inNum2)
打印(十六进制(int.from_字节(字节,'big'))#0x5c
outNum1,outNum2=拆分字节(字节)
打印(outNum1,outNum2)#5 12

您需要首先手动将nybble大小的整数值打包为字节大小的整数值。这是一个简单的算术(或位移位)问题。计算
位长度=最大值(s.bit长度()表示变量中的s)
。如果
位长度>=8
,请使用
num字节=-(.bit长度//8)
避免
数学.log2
。(参考:).PS.假设整数为非负。
def foo(var):
    num_bytes = math.ceil(1 + max(math.log2(x) for x in var)) / 8
    if num_bytes >= 1:
        num_bytes = int(num_bytes)
        return [(i).to_bytes(num_bytes, byteorder='big') for i in var], num_bytes
    elif num_bytes == 0.5:
        shift_bits = 4 # or generally, int(num_bytes * 8) 
        new_list = [(a << shift_bits) + b for a, b in zip(var[::2], var[1::2])]
        return [(i).to_bytes(1, byteorder='big') for i in new_list], num_bytes
def unfoo(var, num_bytes):
    if num_bytes >= 1:
        return [int.from_bytes(i, 'big') for i in var]
    elif num_bytes == 0.5:
        new_list = [int.from_bytes(i, 'big') for i in var]
        ret = []
        shift_bits = 4 # in general: int(num_bytes * 8)
        mask = int(2**shift_bits - 1)
        for i in new_list:
            b = i & mask
            a = (i >> shift_bits) & mask
            ret.append(a)
            ret.append(b)
        return ret
var1 = [1, 5, 4, 17, 231, 89]
var2 = [1, 2, 15, 12]
        
a, b = foo(var1)
c = unfoo(a, b) # prints [1, 5, 4, 17, 231, 89]

print(var1)
print(c)


a2, b2 = foo(var2)
c2 = unfoo(a2, b2) # prints [1, 2, 15, 12]
print(var2)
print(c2)
[1, 5, 4, 17, 231, 89]
[1, 5, 4, 17, 231, 89]
[1, 2, 15, 12]
[1, 2, 15, 12]