- Data Structure
- Networking
- RDBMS
- Operating System
- Java
- MS Excel
- iOS
- HTML
- CSS
- Android
- Python
- C Programming
- C++
- C#
- MongoDB
- MySQL
- Javascript
- PHP
- Physics
- Chemistry
- Biology
- Mathematics
- English
- Economics
- Psychology
- Social Studies
- Fashion Studies
- Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Increment a number by 1 by manipulating the bits
Bit manipulation applies logical operations on a bit stream using bitwise operators like AND(&), OR(|), NOT(~), XOR(^), Left Shift(<<) and Right Shift(>>) to get a required result. Using bitwise operators is beneficial as we can manipulate individual bits and they are faster than other operators.
Problem Statement
Given a number. Increment or add the number by 1 using bitwise operators only. (Don’t use arithmetic operators like ‘+’ , ‘-’, ‘*’ or’/’ )
Approach 1: Using One’s Complement / NOT Operator
Bitwise complement / One’s complement is implemented using the NOT(~) Operator.
For a number n, a bitwise complement of n i.e. ~n = -(n+1). Thus, we can get n+1 by only taking the value of ~n and ignoring the sign. This can be done using the abs() function that returns the variable's value and neglects the sign.
Pseudocode
procedure inc (num) num = |~n| // | | represents the abs() function end procedure
Example
In the following program, we calculate the increment of a number by 1 by using the bitwise complement operator and absolute function.
#include <bits/stdc++.h> using namespace std; // Function for finding the increment of input by 1 int inc(int num){ // using the abs() function to get the value obtained by applying the ~ operator num = abs(~num); return num; } int main(){ int input = 7; cout << input << " + 1 using bit manipulation = " << inc(input); return 0; }
Output
7 + 1 using bit manipulation = 8
Time Complexity − O(1) as no loop is implemented.
Space Complexity − O(1) as no extra space is used.
Approach 2
Take the example of some binary additions as follows,
As a conclusion from the above examples, it can be seen that the binary digits on the left side of the first unset bit from the right of the number remain the same on binary addition of 1. But the first unset bit from the right is set and all the bits on the right side are toggled i.e. set bits are unset and unset bits are set (0’s converted to 1’s and 1’s converted to 0’s).
Thus, we can break our problem into two basic parts,
Set the first unset bit from the right.
Toggle all the bits on the right side.
Recursive Approach Pseudocode
procedure inc (num) if num & 1 == 0 ans = num | 1 else ans = inc (num >> 1) << 1 end if end procedure
Example
In the following program, we are using recursion to increment a number by 1 based on the idea explained above.
#include <bits/stdc++.h> using namespace std; // Function for finding the increment of input int inc(int num){ // check if the LSB is set or not. If it is unset, it enters if otherwise, it goes to else if ((num & 1) == 0) { // LSB is set return num | 1; } else { // The number is right shifted and the function is called again // After obtaining the return number from called function, the number is left shifted return inc(num >> 1) << 1; } } int main(){ int input = 14; cout << input << " + 1 using bit manipulation = " << inc(input); return 0; }
Output
14 + 1 using bit manipulation = 15
Time Complexity − O(k) where k is the position of first unset bit from right.
Space Complexity − O(k) due to the recursive stack space.
Iterative Approach Pseudocode
procedure inc (num) m = 1 while num & m num = num & (~m) m = m << 1 end while num = num | m end procedure
Example
In the following program, we use a mask number that is changed in every iteration till we get the unset bit from the right-hand side. Upon discovering it, the unset bit is set and all the other bits on the right side are toggled.
#include <bits/stdc++.h> using namespace std; // Function for finding the increment of input int inc(int num){ // declare a mask with value 1 which is used to find the first unset bit from right side int m = 1; // checks if LSB is set. If set enter the loop and repeat till we get to the unset bit while (num & m) { num &= ~m; // mask is changed at every iteration to set the unset bit and toggle bits when the loop ends m <<= 1; } // mask used to set the unset bit and toggle all the bits on the right-hand side num |= m; return num; } int main(){ int input = 14; cout << input << " + 1 using bit manipulation = " << inc(input); return 0; }
Output
14 + 1 using bit manipulation = 15
Time Complexity − O(k) where k is the position of first unset bit from right.
Space Complexity − O(1)
Approach 3
In this approach, we approach to reduce the time complexity by reducing the time to find the first unset bit. In this approach, we will first find the first unset bit from the right, set it and toggle all the bits on the right.
Pseudocode
procedure inc (num) pos = log2 (num & ~num) add = 1 << pos num = num | add if pos != 0 toggle = (1 << pos) - 1 num = num ^ toggle end if ans = num end procedure
Example
In the following program, Log2() operation is used to find the unset bit, left shift and OR fro setting the bit and left shift and XOR for toggling bits.
#include <bits/stdc++.h> using namespace std; // Function for finding the increment of input int inc(int num){ // finds the position of the first unset bit from right int pos = log2(num & ~num); // the following 2 operations combined set the unset bit int add = 1 << pos; num |= add; // Toggling bits only for the numbers where the first unset bit was not the LSB if (pos != 0){ // Using left shift and XOR operations to toggle bits int toggle = (1 << pos) - 1; num ^= toggle; } return num; } int main(){ int input = 14; cout << input << " + 1 using bit manipulation = " << inc(input); return 0; }
Output
14 + 1 using bit manipulation = 15
Time Complexity − O(1)
Space Complexity − O(1)
Conclusion
In conclusion, for incrementing a number by 1, we can either use one’s complement concept or by analyzing the nature of bits on the addition of 1 we can follow the above approaches to get the desired result.