Reputation: 33741
Having a bit of trouble fully understanding a basic algo which takes a number x and swaps the bits at positions i and j. The algo is this well-known one
def swap_bits(x, i, j):
if (x >> i) & 1 != (x >> j) & 1:
bit_mask = (1 << i) | (1 << j)
x ^= bit_mask
return x
As I understand it, the algo works by
What I don't fully understand is how the constructing of the bit mask works. I get that the goal of the mask is to identify the subset of bits we want to toggle, but why is (1 << i) | (x << j)
the way to do that? I think I see it for a second, then I lose it.
EDIT:
Think I see it now. We're simply creating two binary numbers, one with a bit set in the i
position and one with a bit set in the j
position. By ORing these, we have a number with bits set in the i
and j
positions. We can apply this mask to our input x
because x ^ 1
= 0 when x = 1
and 1 when x = 0
to swap the bits.
Upvotes: 0
Views: 507
Reputation: 46960
Your initial intuition that something looks fishy is correct. There's a typo:
> def swap_bits(x, i, j):
... if (x >> i) & 1 != (x >> j) & 1:
... bit_mask = (1 << i) | (x << j)
... x ^= bit_mask
... return x
...
>>> swap_bits(0x55555, 1, 2)
1048579
>>> hex(swap_bits(0x55555, 1, 2))
'0x100003'
>>>
The answer should have been 0x55553. A corrected version would have
bit_mask = (1 << i) | (1 << j)
I agree with one of the comments that this method begs for an if
-less implementation. In C:
unsigned swap_bits(unsigned val, int i, int j) {
unsigned b = ((val >> i) ^ (val >> j)) & 1;
return ((b << i) | (b << j)) ^ val;
}
Upvotes: 1