Reputation:
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
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
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
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