Creating a bitmask using BigInts

Is there a more efficient way to do the following calculation? It works fine, but something tells me that x &= (1 << 8) - 1 ^ 1 << 3 can be written to avoid some calculations and increase speed.

 def unset_mask(width, index): return (1 << width) - 1 ^ 1 << index x = 0b11111111 x &= unset_mask(8, 3) assert x == 0b11110111 
+4
source share
3 answers

You don't really need to specify width . Bigtins behave correctly when you do this:

 >>> bin(255 & ~(1 << 3)) '0b11110111' >>> bin(65535 & ~(1 << 3)) '0b1111111111110111' >>> bin(75557863725914323419135 & ~(1 << 3)) '0b1111111111111111111111111111111111111111111111111111111111111111111111110111' 

This is because negative numbers have an β€œinfinite” line of preceding ones . Therefore, when you complement a positive number (which starts with the string "infinte" of zeros), you get a negative number ( -(x + 1) , to be precise). Just don't trust the bin representation of negative numbers; it does not reflect the actual bits in memory.

So you should rewrite unset_mask like this:

 def unset_mask(index): return ~(1 << index) x = 0b11111111 x &= unset_mask(3) print x == 0b11110111 # prints True 
+3
source

This will disable the bit:

 x ^= 1 << 3 & x 

In function:

 def unset_bit(x, n): return 1 << n & x ^ x 
+1
source

You can use this to clear the bit at x :

 x &= ~(1 << index) 
+1
source

All Articles