Basic Bits hacks in Python
Get this book > Problems on Array: For Interviews and Competitive Programming
As a Developer we all want to accomplish a task in the least complexity and time. Bits are proved to be very helpful to achieve it to their operations on integer. There are several time saving methods we are going to discuss that you can adopt to boost the performance on the task.
We have covered the following bit hacks:
 Compute sign of an integer
 Detect if two integer have opposite signs
 Swapping two integer values without third variable
 Determine if an integer is a power of 2
 Negate a Integer value
 Check if the integer is Odd or Even
 To get the Larger (max) or Smaller (min) of two integers without branching
As we all know that bitwise operations are &, , ~, ^, <<, >> and they does operations on the bits of the number. They takes integer as an input and operates on the bit representation of the integer.
First of all below is the overview of some basic concept of Bitwise operations in Python before moving on how we can use these bits to get the most out of the bitwise operation.
Overview of Basic Concepts of Bits

Binary representation in Python
bin() function is used to get binary values of a number. Similarly int() can be used to convert back to decimal.
>>> bin(6)
'0b110'
àº¸

Bitwise AND (&)
It takes two values and does a "bitwise AND". Each bit of the output is 1 if the corresponding bit of x AND of y is 1, otherwise it's 0.
x = 14 1110(in binary)
y = 6 0110(in binary)
>>> x & y
6 0110(in binary)
àº¸

Bitwise OR ()
It takes two values and does a "bitwise OR". Each bit of the output is 0 if the corresponding bit of x AND of y is 0, otherwise it's 1.
x = 14 1110(in binary)
y = 6 0110(in binary)
>>> x  y
14 1110(in binary)
àº¸

Bitwise XOR (^)
It takes two values and does a "bitwise XOR". Each bit of the output is 1 if only one of the inputs is 1, else it's 0.
x = 14 1110(in binary)
y = 6 0110(in binary)
>>> x ^ y
8 1000(in binary)
àº¸

Bitwise 1's complement (~)
Returns the complement of x  the number you get by switching each 1 for a 0 and each 0 for a 1.
Since python integers are signed, the negative numbers are stored through a mechanism called 2's complement format.
x = 14 1110(in binary)
>>> ~x
15 1111(in binary)
àº¸

Bitwise leftshift (<<)
Returns x with the bits shifted to the left by y places.
x = 5 0101(in binary)
y = 2
>>> x << y
20 10100(in binary)
àº¸

Bitwise rightshift (<<)
Returns x with the bits shifted to the right by y places.
x = 5 0110(in binary)
y = 2
>>> x >> y
1 0001(in binary)
àº¸
Twirling hacks using bits
àº¸
From the above, you should get the basic working of the Bitwise working of the integer. Now, lets twirl these bits knowledge to enhance the functionality of the bits.

Compute sign of an integer
It will compute the sign of the integer whether it is negative or positive integer. Sign will output 1 for negative integer, 0 , or +1 for positive value.
v = 20
>>> sign = (v > 0)  (v < 0)
>>> print(sign)
1 # as 20 is negative
àº¸

Detect if two integer have opposite signs
We will use XOR to get the bits of the number and check if it is less than 0 or not. Decimal output of the XOR is then compared to 0. Output will be 'True' if both integers have opposite signs, else 'False'.
x = 7 0111
y = 2 0010
x ^ y = 0101 = 5(in decimal)
>>> sign = ((x ^ y) < 0)
>>> print(sign)
'True'
àº¸

Swapping two integer values without third variable
Generally, people use a third variable to swap two integer values which can be expensive. Values can be swapped using the OR operator.
a = 4 0100
b = 11 1011
>>> a = a ^ b a = 1111
>>> b = b ^ a b = 0100 (4 in decimal)
>>> a = a ^ b a = 1011 (11 in decimal)
>>> print('a= ', a)
>>> print('b= ', b)
a= 11
b= 4
àº¸

Determine if an integer is a power of 2.
We can check if an integer is a power of two. For example, 16 can be represented as 2^4 and 12 cannot be represented as a power of 2.
v = 16 10000(in binary)
>>> res = (v & (v  1)) == 0
True
v = 12 1100(in binary)
>>> res = (v & (v  1)) == 0
False
In the above example, it will apply the AND operation on 16 and 15, and if there AND operation give 0 then the integer is the power of 2.
àº¸

Negate a Integer value
We can also negate a integer value but we have to use a boolean variable that should be True to help in negating the integer value.
Negate = True
v = 3
>>> r = (v ^ fNegate) + fNegate;
>>> print(r)
3
àº¸

Check if the integer is Odd or Even
 A simple logic To AND operate the integer with 1 to check if the integer is Odd or else Even.
v = 37
>>> if(v & 1):
>>> print(v, 'is Odd')
>>> else:
>>> print(v, 'is Even')
37 is Odd
 To use a boolean variable that is set to False and will tell if the integer is Odd or Even.
v = 37
flag = False
>>> while (v):
>>> flag = not(flag)
>>> v = v & (v  1)
True
As compared to 1st method, 2nd seems to be confusing but it just a matter of logic to get the work done.
àº¸

To get the Larger (max) or Smaller (min) of two integers without branching
To calculate the larger or smaller between the two integer can be very expensive while operating on a huge number of comparison using branching. The bits operation can help to reduce the time.
To get the larger integer
x = 2
y = 6
>>> res = x ^ ((x ^ y) & ~(x < y))
>>> print("Larger is: ", res)
Larger is: 6
It works as if x<y, then ~(x<y) will be all ones, so r = x ^ (x ^ y) & ~0 = x ^ x ^ y = y (as y=6 is greater than x=2). Otherwise if x>=y, then ~(x < y) will be all zeros, so r =x ^ ((x ^ y) & 0) = x.
To get the smaller integer
To get the minimum integer the logic is same as of maximum. The only replacement is 'y' in place of 'x'. res = y ^ ((x ^ y) & ~(x < y))
x = 2
y = 6
>>> res = y ^ ((x ^ y) & ~(x < y))
>>> print("Smaller is: ", res)
Smaller is: 2