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

标签 python type-conversion byte bit

我有一个整数列表:

var = [1, 5, 4, 17, 231, 89]

如果我想将其转换为字节列表,我可以这样做:

[(i).to_bytes(1, byteorder='big') for i in var]

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

var = [1, 2, 15, 12]

这可以将一个整数放入半个字节,或者更准确地说是我要查找的内容,每个字节放入两个整数。

如果可能的话,我如何指定将两个整数组合成一个字节,包括往返?

类似下面的内容:

var1 = [1, 5, 4, 17, 231, 89]
var2 = [1, 2, 15, 12]

def foo(var):
  if max(var) < 2**4:
    num_bytes = 0.5
  elif max(var) < 2**8:
    num_bytes = 1
  elif max(var) < 2**16:
    num_bytes = 2

  if num_bytes >= 1:
    return [(i).to_bytes(num_bytes, byteorder='big') for i in var], num_bytes
  elif num_bytes = 0.5:
    # convert var to list of nybbles
    # combine two nybbles to a byte
    # create list of bytes (length is half length of var)
    # return it and num_bytes

def unfoo(var, num_bytes):
  if num_bytes >= 1:
    print([int.from_bytes(i, 'big') for i in var])
  elif num_bytes = 0.5:
    # print original list of integers again

我想将一个整数列表转换为一个字节列表,但如果可以的话,将两个半字节放入一个字节,然后再进行转换。

期望的结果是:

a, b = foo(var1)
unfoo(a, b) # prints [1, 5, 4, 17, 231, 89]

a, b = foo(var2)
unfoo(a, b) # prints [1, 2, 15, 12]

我不想要一个最小位数的列表来表示一个数字。注意max(list):如果列表中的所有值都可以是8位,则将其调整为8位;如果所有值都可以是 16 位,则适合 16 位;如果所有值都可以是 nybble,则将两个 nybble 对组成一个字节列表。

基本上,如果我有两个整数,每个整数都可以放入一个 nybble,我该如何将它们连接成一个字节?如果我知道需要将字节分成两部分,我该怎么做呢?我总是可以假设原始列表可以被 2 整除。

最佳答案

您需要计算一个字节可以容纳多少个数字。然后,您需要将每个数字移动正确的数量并创建一个包含组合数字的新列表。假设你可以在一个字节中容纳两个数字,你会得到 new_number = (old_num1 << 4) + old_num2

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

收件人unfoo ,您需要执行此操作的逆操作:当 num_bytes < 1 时,我们可以在 foo() 中找到您移动的位数功能。按照与前面解释相同的名称,并给出 new_number , 我们可以得到 old_num2作为最低有效的四位(由 new_number & mask 找到)和 old_num1是最重要的四位(由 new_number >> shift_bits 找到)

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]

关于python - 将整数转换为半字节, `to_bytes()`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66856988/

相关文章:

c# - 将文本框文本转换为整数

c++ - 是否存在 x + 1 == x 类型的 float 值 x?

sql-server - SQL Server 2008 将 VARCHAR(50) 转换为唯一标识符

c# - 使用字节访问位图内存信息

java - 将 Java 方法 Base64.encodeToString() 转换为 PHP

python - 如何对数据透视表上的值进行分组?

python - SQLAlchemy 说 "Table already exists"虽然它没有

python - 通过 numpy.random.seed 设置的随机种子是否跨子模块维护?

python - `key=function` 中的 `sorted(tuple, key=function)` 是如何工作的?

java - 我如何从java中的InputStream中提取某些模式,然后放入byteArray中