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)
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.
You can test for individual bits using bitwise operators and bit shifts. The part that must be new to you, is the >> operator. This operator will "insert a zero on the left and push every bit to the right, and the rightmost will be thrown away".
To loop through a set of code a specified number of times, we can use the range() function, The range() function returns a sequence of numbers, starting from 0 by default, and increments by 1 (by default), and ends at a specified number.
This bit numbering method has the advantage that for any unsigned number the value of the number can be calculated by using exponentiation with the bit number and a base of 2. The value of an unsigned binary integer is therefore
Most significant bit first means that the most significant bit will arrive first: hence e.g. the hexadecimal number 0x12, 00010010 in binary representation, will arrive as the sequence 0 0 0 1 0 0 1 0 .
Rather, it is a property of the numeric value in binary itself. This is often utilized in programming via bit shifting: A value of 1 << n corresponds to the nth bit of a binary integer (with a value of 2 n ).
where bi denotes the value of the bit with number i, and N denotes the number of bits in total. When the bit numbering starts at zero for the most significant bit (MSB) the numbering scheme is called MSB 0 .
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)
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With