简体   繁体   English

Python - 从 8 个布尔字节值生成和 int,反之亦然

[英]Python - making and int from 8 boolean byte values and vice versa

I have 8 bool variables, and I want to "merge" them into a byte.我有 8 个 bool 变量,我想将它们“合并”成一个字节。

Is there an easy/preferred method to do this?有没有一种简单/首选的方法来做到这一点?

How about the other way around, decoding a byte into 8 separate boolean values?反过来,如何将一个字节解码为 8 个单独的布尔值?

Examples:例子:

>>> byte_to_number([False, True, True, True, True, False, True, True])

123

>>> number_to_byte(123)

[False, True, True, True, True, False, True, True]

You can use a list comprehension to iterate through each item in the list, then an int() to convert the binary value to an integer.您可以使用列表理解来遍历列表中的每个项目,然后使用int()将二进制值转换为整数。

>>> a = [False, True, True, True, True, False, True, True]
>>> int("".join(["01"[i] for i in a]), 2)
123
>>> 
import math

def bools_to_int(bits):
    value = 0
    for i, bit in enumerate(bits):
        value |= bit << (len(bits) - i - 1)
    return value
    
def int_to_bools(value):
    bits = []
    n = math.ceil(math.log2(value))
    for i in range(n):
        bits.append(value >> (n - i - 1) & 1 == 1)
    return bits
    
print(bools_to_int([False, True, True, True, True, False, True, True]))
# Outputs 123

print(int_to_bools(123))
# Outputs [True, True, True, True, False, True, True]

You can also add a padding parameter to int_to_bools if you want the leading digits:如果需要前导数字,还可以向int_to_bools添加填充参数:

def int_to_bools(value, pad=-1):
    bits = []
    n = max(pad, math.ceil(math.log2(value)))
    for i in range(n):
        bits.append(value >> (n - i - 1) & 1 == 1)
    return bits

print(int_to_bools(123, pad=8))
# Outputs [False, True, True, True, True, False, True, True]

You can also add a endian parameter to both functions if you want to control how the bits are parsed:如果要控制位的解析方式,还可以向这两个函数添加字节序参数:

import math

def bools_to_int(bits, big_endian=True):
    value = 0
    for i, bit in enumerate(bits):
        shift = (len(bits) - i - 1) if big_endian else i 
        value |= bit << shift
    return value
    
def int_to_bools(value, pad=-1, big_endian=True):
    bits = []
    n = max(pad, math.ceil(math.log2(value)))
    for i in range(n):
        shift = (n - i - 1) if big_endian else i
        bits.append(value >> shift & 1 == 1)
    return bits
    
print(bools_to_int([False, True, True, True, True, False, True, True], big_endian=True))
# Outputs 123, parse as 01111011

print(bools_to_int([False, True, True, True, True, False, True, True], big_endian=False))
# Outputs 222, parse as 11011110

You can do this a little bit easier with just straight bitwise operators您可以使用直接的按位运算符更轻松地完成此操作

def byte_to_number(bools):
    return ((1 if bools[0] else 0) << 0) | \
           ((1 if bools[1] else 0) << 1) | \
           ((1 if bools[2] else 0) << 2) | \
           ((1 if bools[3] else 0) << 3) | \
           ((1 if bools[4] else 0) << 4) | \
           ((1 if bools[5] else 0) << 5) | \
           ((1 if bools[6] else 0) << 6) | \
           ((1 if bools[7] else 0) << 7)

def number_to_byte(num):
    return [bool((num >> i) & 1) for i in range(8)]

This always assumes you only want an 8 bit number to work with, avoiding arbitrary length for loops.这始终假设您只想要一个 8 位数字,避免任意长度的循环。

For the opposite endian order, only the range needs to be reversed:对于相反的 endian 顺序,只需要反转范围:

def number_to_byte(num):
    return [bool((num >> i) & 1) for i in reversed(range(8))]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM