Mastering Bit Manipulation in Java
Bit manipulation is a powerful technique in programming that can help you solve problems more efficiently. It involves using bitwise operators to manipulate individual bits in a number, which can lead to faster and more compact code. In this post, we’ll explore some common bit manipulation techniques in Java and how to use them effectively.
Bitwise Operators
Before we dive into bit manipulation, let’s review the bitwise operators in Java:
- & (and) — performs a bitwise AND operation between two numbers, resulting in a new number where each bit is 1 if and only if both corresponding bits are 1.
- | (or) — performs a bitwise OR operation between two numbers, resulting in a new number where each bit is 1 if either corresponding bit is 1.
- ^ (xor) — performs a bitwise XOR operation between two numbers, resulting in a new number where each bit is 1 if and only if exactly one corresponding bit is 1.
- ~ (not) — performs a bitwise NOT operation on a number, resulting in a new number where each bit is the opposite of its corresponding bit in the original number.
- << (left shift) — shifts the bits of a number to the left by a specified number of positions, effectively multiplying the number by 2 to the power of the shift amount.
- Arithmetic/signed right shift:
>>
is the arithmetic (or signed) right shift operator. - Logical/unsigned right shift:
>>>
is the logical (or unsigned) right shift operator.
Using Bitwise Operators
Now that we understand the bitwise operators, let’s look at some common use cases for bit manipulation.
- Set a Bit
To set a particular bit in a number to 1, we can use the OR operator with a bit mask. For example, to set the third bit of a number to 1, we can use the following code:
int num = 5; // 00000101
int bitMask = 1 << 2; // 00000100
int result = num | bitMask; // 00000101 | 00000100 = 00000101
The
bitMask
is created by shifting the number 1 to the left by the number of positions we want to set. In this case, we shift 1 to the left by 2 positions to get00000100
. Then we use the OR operator to set the third bit ofnum
to 1.
2. Clear a Bit
To clear a particular bit in a number to 0, we can use the AND operator with a bit mask. For example, to clear the third bit of a number to 0, we can use the following code:
int num = 7; // 00000111
int bitMask = ~(1 << 2); // 11111011
int result = num & bitMask; // 00000111 & 11111011 = 00000101
The
bitMask
is created by taking the complement of a bit mask that has a 1 in the position we want to clear and 0s everywhere else. In this case, we create a bit mask with a 1 in the third position by shifting 1 to the left by 2 positions and then taking the complement using the NOT operator. This gives us11111011
. Then we use the AND operator to clear the third bit ofnum
.
3. Toggle a Bit
To toggle a particular bit in a number, we can use the XOR operator with a bit mask. For example, to toggle the third bit of a number, we can use the following code:
int num = 6; // 00000110
int bitMask = 1 << 2; // 00000100
int result = num ^ bitMask; // 00000110 ^ 00000100 = 00000010
The
bitMask
is created in the same way as in the previous example. Then we use the XOR operator to toggle the third bit ofnum
.
4. Check if a Bit is Set
To check if a particular bit in a number is set, we can use the AND operator with a bit mask. For example, to check if the third bit of a number is set, we can use the following code:
int num = 5; // 00000101
int bitMask = 1 << 2; // 00000100
boolean isSet = (num & bitMask) != 0; // (00000101 & 00000100) != 0 => true
We use the AND operator to check if the third bit of
num
is set. If the result is not equal to 0, then the bit is set.
5. Bit Count
To count the number of bits set to 1 in a number, we can use the built-in Integer.bitCount()
method. For example:
int num = 7; // 00000111
int count = Integer.bitCount(num); // 3
This method counts the number of bits set to 1 in a number using a fast algorithm.
6. Check if a Number is Power of Two
To check if a given number is a power of two, we can use the bitwise AND operator. A number that is a power of two will have only one bit set to 1. For example:
int num = 16; // 00010000
boolean isPowerOfTwo = (num & (num - 1)) == 0; // true
Here, we use the bitwise AND operator to check if
num
andnum - 1
have any common set bits. If they don't, it means thatnum
has only one bit set to 1, and is therefore a power of two.
7. Swap Two Numbers
We can swap the values of two variables without using a temporary variable using bitwise XOR operator. For example:
int a = 5; // 00000101
int b = 9; // 00001001
a = a ^ b; // a = 00001100
b = a ^ b; // b = 00000101
a = a ^ b; // a = 00001001
Here, we use bitwise XOR to swap the values of
a
andb
without using a temporary variable.
8. Check if a Number is Even or Odd
To check if a given number is even or odd, we can use the bitwise AND operator. An even number will have its least significant bit (rightmost bit) set to 0, while an odd number will have it set to 1. For example:
int num = 6; // 00000110
boolean isEven = (num & 1) == 0; // true
Here, we use the bitwise AND operator to check if the least significant bit of
num
is set to 0 or 1. If it's 0, thennum
is even, otherwise it's odd.
9. Set All Bits to 1
To set all bits of a number to 1, we can use the bitwise NOT operator (~) with 0. For example:
int num = 5; // 00000101
int allOnes = ~0; // 11111111 11111111 11111111 11111111
int result = num | allOnes; // 11111111 11111111 11111111 11111101
Here, we use the bitwise NOT operator to create a number with all bits set to 1, and then use the bitwise OR operator to set all bits of
num
to 1.
10. Convert Characters to Uppercase or Lowercase
We can convert a character to uppercase or lowercase using bitwise OR operator and bitwise XOR operator. Here’s an example:
char c = 'a'; // lowercase 'a' in ASCII
char upperC = (char) (c & ~32); // uppercase 'A' in ASCII or use c ^ 32
char lowerC = (char) (c | 32); // lowercase 'a' in ASCII
In the ASCII character set, the difference between uppercase and lowercase letters is a single bit in the sixth position. The uppercase letter has this bit set to 0, while the lowercase letter has it set to 1. To convert a lowercase letter to uppercase, we can use the bitwise AND operator with the bit mask
~32
, which sets the sixth bit to 0. To convert an uppercase letter to lowercase, we can use the bitwise OR operator with the bit mask32
, which sets the sixth bit to 1.In the example above, we convert the character ‘a’ to uppercase and lowercase using these bitwise operations. We use a type cast to convert the result back to a char data type.
By using these bitwise tricks, you can convert characters to uppercase or lowercase without using any string manipulation functions, which can be useful in situations where you need to optimize your code for performance.
Conclusion
In this post, we’ve covered some common bit manipulation techniques in Java. Bit manipulation can be a powerful tool in programming, but it’s important to use it judiciously and only when necessary. By using these techniques, you can write faster and more efficient code that can handle large amounts of data with ease.
I hope you found this post helpful. If you have any questions or comments, please feel free to leave them below!
Ref : https://www.educative.io/blog/bit-manipulation-in-java