I have an integer with a value 7
(0b00000111
) And I would like to replace it with a function to 13
(0b00001101
). What is
Going by the examples provided, it sounds like you are looking to swap bits in an integer.
For example in 7 (0b00000111)
, if you swap the bits in the 3rd and 1st positions you obtain 13 (0b00001101)
.
I would have the following as a function signature swap_bits(val, i, j)
What is the best algorithm? Well, the following algorithm takes constant time, O(1).
def swap_bits(val, i, j):
"""
Given an integer val, swap bits in positions i and j if they differ
by flipping their values, i.e, select the bits to flip with a mask.
Since v ^ 1 = 0 when v = 1 and 1 when v = 0, perform the flip using an XOR.
"""
if not (val >> i) & 1 == (val >> j) & 1:
mask = (1 << i) | (1 << j)
val ^= mask
return val
Example:
>>> swap_bits(7, 3, 1)
13
The code leverage bit twiddling tricks and here is a good resource by Sean Anderson. I am working on providing the code snippets in Python here.
You can use bitwise opertions. http://wiki.python.org/moin/BitwiseOperators
if you want to set a given bit to 1 you can use bitwise 'or' with 1 on given position:
0b00000111 | 0b00001000 = 0b00001111
to set a given bit to 0 you can use bitwise 'and'
0b00001111 & 0b11111011 = 0b00001011
Note that 0b prefix is for binary numbers and 0x is for hexadecimal.
You just need:
def set_bit(v, index, x):
"""Set the index:th bit of v to 1 if x is truthy, else to 0, and return the new value."""
mask = 1 << index # Compute mask, an integer with just bit 'index' set.
v &= ~mask # Clear the bit indicated by the mask (if x is False)
if x:
v |= mask # If x was True, set the bit indicated by the mask.
return v # Return the result, we're done.
>>> set_bit(7, 3, 1)
15
>>> set_bit(set_bit(7, 1, 0), 3, 1)
13
Note that bit numbers (index
) are from 0, with 0 being the least significant bit.
Also note that the new value is returned, there's no way to modify an integer "in place" like you show (at least I don't think so).
These work for integers of any size, even greater than 32 bit:
def set_bit(value, bit):
return value | (1<<bit)
def clear_bit(value, bit):
return value & ~(1<<bit)
If you like things short, you can just use:
>>> val = 0b111
>>> val |= (1<<3)
>>> '{:b}'.format(val)
'1111'
>>> val &=~ (1<<1)
'1101'