Bitwise Tricks Or Regret Later
Tricks 1 : check if a number is a power of 2 using its binary representation in C++
A number is a power of 2 if it has exactly one bit set to 1
in its binary representation. You can use the following approach to check this:
- A power of 2 number has only one set bit. For example:
2^0 = 1
→0001
2^1 = 2
→0010
2^2 = 4
→0100
To check this, you can use the property:
- If
n
is a power of 2, then(n & (n - 1))
will be0
.
Here’s the C++ code for checking if a number is a power of 2 using this idea:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
int main()
{
int num;
cout << "Enter a number: ";
cin >> num;
// Check if the number is positive and a power of 2
if (num > 0 && (num & (num - 1)) == 0)
{
cout << num << " is a power of 2." << endl;
}
else
{
cout << num << " is not a power of 2." << endl;
}
return 0;
}
Tricks 2: Playing with the k th bit
-
Check if k-th bit is set: You can use the bitwise AND operator to check if the k-th bit is set (1).{x&(1«k)}
1 2 3
bool isKthBitSet(int n, int k) { return (n & (1 << (k - 1))) != 0; }
This shifts the number
1
to the left byk-1
positions, and then the bitwise AND checks if that bit inn
is 1. -
Set the k-th bit: To set the k-th bit (turn it into 1), you use the bitwise OR operator. {x or (1«k)}
1 2 3
int setKthBit(int n, int k) { return n | (1 << (k - 1)); }
This ensures the k-th bit is set to 1, leaving other bits unchanged.
-
Clear/unset the k-th bit: To clear the k-th bit (turn it into 0), use the bitwise AND with the complement of the shifted bit.{x&n(1«k)}
1 2 3
int clearKthBit(int n, int k) { return n & ~(1 << (k - 1)); }
The expression
~(1 << (k - 1))
generates a mask that has all bits set to 1 except the k-th bit, which is 0. -
Toggle the k-th bit: To toggle the k-th bit (flip it from 1 to 0 or 0 to 1), use the bitwise XOR operator.{X^(1«k)}
1 2 3
int toggleKthBit(int n, int k) { return n ^ (1 << (k - 1)); }
-
Turn off all bits except the k-th: This keeps only the k-th bit turned on (if set) and turns off all other bits.
1 2 3
int keepOnlyKthBit(int n, int k) { return n & (1 << (k - 1)); }
Tricks 3: Multiply or Divide a number by $k^2$
Multiply by $2^k$: (Left shift (<<
)is used to multiply a number by $2^k$)
To multiply a number by $2^k$, use the left shift operator (<<
).
Code:
1
2
3
int multiplyByTwoPowerK(int n, int k) {
return n << k;
}
Explanation:
n << k
shifts the bits ofn
to the left byk
positions. This is equivalent to multiplyingn
by 2k.- For example,
n << 3
is equivalent to multiplyingn
by 23=8.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
int multiplyByTwoPowerK(int n, int k) {
return n << k;
}
int main() {
int n = 5;
int k = 3;
cout << "5 multiplied by 2^3 is: " << multiplyByTwoPowerK(n, k) <<endl; // Output: 40
return 0;
}
Output:
1
2
5 multiplied by 2^3 is: 40
Divide by $2^k$:(Right shift (>>
)is used to divide a number by $2^k$)
To divide a number by $2^k$, use the right shift operator (>>
).
Code:
1
2
3
int divideByTwoPowerK(int n, int k) {
return n >> k;
}
Explanation:
n >> k
shifts the bits ofn
to the right byk
positions. This is equivalent to dividingn
by 2k (ignoring the remainder for integers).- For example,
n >> 3
is equivalent to dividingn
by 23=8.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
int divideByTwoPowerK(int n, int k) {
return n >> k;
}
int main() {
int n = 40;
int k = 3;
cout << "40 divided by 2^3 is: " << divideByTwoPowerK(n, k) <<endl; // Output: 5
return 0;
}
Output:
1
40 divided by 2^3 is: 5
Tricks 4: Find out x % $2^k$
To find x % 2^k
using bitwise operations in C++, you can use the fact that modulo by a power of 2 can be computed efficiently using a bitwise AND operation.
Given that 2^k
is a power of 2, its binary representation is a 1 followed by k
zeros. So, x % 2^k
is equivalent to taking the lowest k
bits of x
, which can be done with the following expression:
1
x & ((1 << k) - 1)
Here’s a breakdown of how this works:
1 << k
shifts1
to the left byk
positions, which gives2^k
.- Subtracting
1
from2^k
gives a number with the lowestk
bits set to1
. - Performing a bitwise AND between
x
and this mask effectively keeps the lowestk
bits ofx
(which gives youx % 2^k
).
Example code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
int main() {
int x = 29; // Example value
int k = 3; // Example value for k
int result = x & ((1 << k) - 1);
cout << x << " % " << (1 << k) << " = " << result << endl;
return 0;
}
Explanation:
- For
x = 29
(which is11101
in binary) andk = 3
, you want to find29 % 2^3 = 29 % 8
. 1 << 3
gives8
(which is1000
in binary).8 - 1
gives7
(which is111
in binary).29 & 7
gives5
(which is101
in binary), so29 % 8 = 5
.
This approach is efficient and works in constant time.
Tricks 5: Swap two numbers, X and Y, without a temporary variable
You can swap two numbers, X
and Y
, without using a temporary variable using bitwise XOR. Here’s how it works:
Explanation:
The XOR operation has the following properties:
A ^ A = 0
A ^ 0 = A
A ^ B ^ A = B
(XOR is commutative and associative)
Using these properties, the following steps swap X
and Y
:
X = X ^ Y;
(NowX
holds the result ofX ^ Y
)Y = X ^ Y;
(SinceX = X ^ Y
now,Y = (X ^ Y) ^ Y = X
—soY
holds the original value ofX
)X = X ^ Y;
(NowX = (X ^ Y) ^ X = Y
—soX
holds the original value ofY
)
C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
int main() {
int X = 5;
int Y = 10;
// Before swapping
cout << "Before swapping: X = " << X << ", Y = " << Y << endl;
// XOR swap algorithm
X = X ^ Y;
Y = X ^ Y;
X = X ^ Y;
// After swapping
cout << "After swapping: X = " << X << ", Y = " << Y << endl;
return 0;
}
Output:
1
2
3
Before swapping: X = 5, Y = 10
After swapping: X = 10, Y = 5
This method uses only bitwise XOR operations and does not require any extra memory or temporary variables.
Tricks 6:
1
2
3
4
5
6
property: no. of set bits in A = X
no. of set bits in B = Y
no. of set bit in (A^B) = Z
Then,
z is even if x+y is even
z is odd of x+y is odd`
The property you’re describing relates to the number of set bits in the binary representation of numbers A
, B
, and their XOR result (A ^ B)
.
Here’s how it works:
- The number of set bits in
A
is denoted byX
. - The number of set bits in
B
is denoted byY
. - The number of set bits in
(A ^ B)
is denoted byZ
.
The XOR Operation and Set Bits:
- The XOR operation results in
1
only when the bits of the two numbers differ. - If both
A
andB
have the same bit in a particular position (either0
or1
), XOR will result in0
for that position. - Thus, the number of set bits in
(A ^ B)
depends on how different the bit patterns ofA
andB
are.
The property:
- If
X + Y
is even,Z
(the number of set bits in(A ^ B)
) is even. - If
X + Y
is odd,Z
is odd.
C++ Code to Check:
You can use the following C++ code to verify this property:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
using namespace std;
// Function to count the number of set bits in a number
int countSetBits(int n) {
int count = 0;
while (n) {
count += n & 1; // Increment count if the least significant bit is 1
n >>= 1; // Right shift n by 1 bit
}
return count;
}
int main() {
int A = 5; // Example value
int B = 10; // Example value
int X = countSetBits(A); // Number of set bits in A
int Y = countSetBits(B); // Number of set bits in B
int Z = countSetBits(A ^ B); // Number of set bits in A ^ B
cout << "Set bits in A (X): " << X << endl;
cout << "Set bits in B (Y): " << Y << endl;
cout << "Set bits in (A ^ B) (Z): " << Z << endl;
if ((X + Y) % 2 == 0) {
cout << "Since X + Y is even, Z is even: " << ((Z % 2 == 0) ? "True" : "False") << endl;
} else {
cout << "Since X + Y is odd, Z is odd: " << ((Z % 2 != 0) ? "True" : "False") << endl;
}
return 0;
}
Explanation:
- The
countSetBits
function counts the number of set bits (1’s) in the binary representation of a number by repeatedly checking the least significant bit usingn & 1
and right-shifting the number by 1 bit. - The program then checks the property: If
X + Y
is even,Z
is even, and ifX + Y
is odd,Z
is odd.
Example:
For A = 5
(binary 101
), B = 10
(binary 1010
):
X = 2
(two 1’s in101
)Y = 2
(two 1’s in1010
)A ^ B = 15
(binary1111
, four 1’s), soZ = 4
.
Since X + Y = 2 + 2 = 4
is even, Z
is even, and the output will confirm this.