user16471176
user16471176

Reputation:

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.

Is there an easy/preferred method to do this?

How about the other way around, decoding a byte into 8 separate boolean values?

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]

Upvotes: 0

Views: 594

Answers (3)

Josh Weinstein
Josh Weinstein

Reputation: 2968

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.

For the opposite endian order, only the range needs to be reversed:

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

Upvotes: 0

enzo
enzo

Reputation: 11531

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:

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

Upvotes: 0

user9321739
user9321739

Reputation:

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.

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

Upvotes: 1

Related Questions