7

How can I iterate and evaluate the value of each bit given a specific binary number in python 3?

For example:

00010011 
--------------------
bit position | value
--------------------
[0]            false (0)
[1]            false (0)
[2]            false (0)
[3]            true  (1)
[4]            false (0)
[5]            false (0)
[6]            true  (1)
[7]            true  (1)
7
  • 2
    Is your 'binary number' a string? Commented May 20, 2013 at 23:39
  • 2
    What have you tried so far? Is your 'binary number' a string (so a sequence of 0 and 1 characters)? Commented May 20, 2013 at 23:39
  • @MartijnPieters it's a binary number parsed from an integer with bin() Commented May 20, 2013 at 23:40
  • 2
    [ bool(int(x)) for x in "00010011" ] would yield [False, False, False, True, False, False, True, True]. Is this what you aim for? Commented May 20, 2013 at 23:40
  • 1
    @Rafael Your given example is then impossible. bin() will never give you leading 0s. And it'll be prefixed with 0b. Commented May 20, 2013 at 23:41

6 Answers 6

18

It's better to use bitwise operators when working with bits:

number = 19

num_bits = 8
bits = [(number >> bit) & 1 for bit in range(num_bits - 1, -1, -1)]

This gives you a list of 8 numbers: [0, 0, 0, 1, 0, 0, 1, 1]. Iterate over it and print whatever needed:

for position, bit in enumerate(bits):
    print '%d  %5r (%d)' % (position, bool(bit), bit)
Sign up to request clarification or add additional context in comments.

2 Comments

This is the way to go. Bit operations on numbers are also much faster than splitting and stitching strings.
If you don't know the least number of bits required to represent a number, you can do len(bin(number)) - 2. bin(number) gives you 0b1010101, so you get the string's length and take 2 out of it.
5

Python strings are sequences, so you can just loop over them like you can with lists. Add enumerate() and you have yourself an index as well:

for i, digit in enumerate(binary_number_string):
    print '[{}] {:>10} ({})'.format(i, digit == '1', digit)

Demo:

>>> binary_number_string = format(19, '08b')
>>> binary_number_string
'00010011'
>>> for i, digit in enumerate(binary_number_string):
...     print '[{}] {:>10} ({})'.format(i, digit == '1', digit)
... 
[0]      False (0)
[1]      False (0)
[2]      False (0)
[3]       True (1)
[4]      False (0)
[5]      False (0)
[6]       True (1)
[7]       True (1)

I used format() instead of bin() here because you then don't have to deal with the 0b at the start and you can more easily include leading 0.

3 Comments

+1. As a note, while I appreciate matching the output exactly, I'm slightly scared the OP will use this verbatim and do checks against "true" and "false" - to be clear, in general code, use the actual bool values True and False.
@Lattyware well i'm not in that n00b level
@Rafael You'd be surprised at the level of programmer I see doing stuff like that. I tend to assume the worst.
3

Surprisingly, converting the integer to a string is quite a bit faster than using binary operations. Benchmarking on a Core i9 running MacOS 10.15 with Python 3.7.6:

In [6]: number = 1 << 30

In [7]: num_bits = 32

In [8]: %timeit bits = [c == '1' for c in format(number, f'0{num_bits}b')]
1.84 µs ± 8.51 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [9]: %timeit bits = [(number >> bit) & 1 for bit in range(num_bits - 1, -1, -1)]
3.13 µs ± 69.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

The format() approach runs in 60% of the time of the bitwise operators approach! (Nor is it changed much if you add an if-else to get a list of integers instead of booleans.)

I assume this is because Python integers are stored behind the scenes in a way that doesn't allow for efficient bitwise operations.

Comments

0

Why bother with strings? This code is for 8 bits, but changing it should be obvious:

num = 19
bits = [False for i in range(8)]
for i in range(8):
    bits[7-i] = True if num & 1 else False
    num = num >> 1

print(bits)

Comments

0

This list comprehension will give you the data you need. Do you also want it formatted under table?

>>> [(i, b=='1', b) for i, b in enumerate('00010011')]
[(0, False, '0'), (1, False, '0'), (2, False, '0'), (3, True, '1'),
 (4, False, '0'), (5, False, '0'), (6, True, '1'), (7, True, '1')]

Comments

0
num=19

for val in [bool(num & (1<<n)) for n in range(8)]:
    print(val)
    # do stuff

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.