Bit Manipulation

Bit Manipulation is a powerful technique employed in numerous problem-solving scenarios to derive optimized solutions. Particularly prevalent in Competitive Programming, this method revolves around the utilization of Bitwise Operators that operate directly on the binary representations or individual bits of numbers, enhancing implementation efficiency. The following are some key Bitwise Operators commonly utilized in this process:

  • Bitwise XOR (^): The Bitwise XOR operator (^) compares each bit of two operands. It returns 1 if the bits are different, and 0 if they are the same.

  • Bitwise NOT (!): The Bitwise NOT operator (!) inverts each bit of the operand, turning 0s into 1s and 1s into 0s.

  • Bitwise AND (&): The Bitwise AND operator (&) compares corresponding bits of two operands. It returns 1 only if both bits are 1, otherwise, it returns 0.

  • Bitwise OR (|): The Bitwise OR operator (|) compares corresponding bits of two operands. It returns 1 if at least one of the bits is 1.

Bit representation

In the realm of programming, an n-bit integer is internally stored as a binary number comprising n bits. For instance, the int type in C++ is a 32-bit type, implying that each int number is made up of 32 bits.

Let's take the int number 43 as an example:
43 = 00000000000000000000000000101011

The bits in this representation are typically indexed from right to left. To translate a bit representation bk ···b2 b1 b0 into a number, the formula bk2k +…+ b222 + b121 + b020 can be applied.
For instance, 1·25 + 1·23 + 1·21 + 1·20 equals 43.

It's important to note that the bit representation of a number can be either signed or unsigned.
In most cases, a signed representation is utilized, allowing for the representation of both negative and positive numbers.
A signed variable of n bits can contain any integer between -2n-1 and 2n-1 – 1
The int type in C++ is a signed type, so an int variable can contain any integer between -231 and 231 – 1.

The first bit in a signed representation serves as the sign indicator for the number, with 0 representing non-negative numbers and 1 indicating negative numbers. The remaining n−1 bits store the magnitude of the number.

In signed representation, two’s complement is employed, where the negative of a number is derived by flipping all the bits in the number and then adding one to the result. For instance, the binary representation of the integer −43 is 11111111111111111111111111010101.

Conversely, in an unsigned representation, only non-negative numbers are accommodated, but the range of values extends further. An unsigned variable with n bits can encompass any integer between 0 and 2n − 1.

Within C++, an unsigned int variable is capable of holding any integer from 0 to 232 − 1. There exists a correlation between these representations: a signed number ���x corresponds to an unsigned number 2n − x. For example, consider the following pseudo-code snippet demonstrating that the signed number x = −43 equates to the unsigned number y = 232 − 43:

Bitwise Operations:

Let's delve into the world of Bitwise Operations. These operations manipulate individual bits within binary numbers. They are fundamental in computer science and are often used for tasks like data encryption, compression, and device control.

In the table below, we will explore the outcomes when various operations are executed using Bitwise Operators. The terms 0s or 1s represent a series of 0 or 1 respectively. Understanding these operations is crucial for low-level programming and optimizing code for performance.

OperatorsOperationsResult
XORX ^ 0sX
XORX ^ 1s~X
XORX ^ X0
ANDX & 0s0
ANDX & 1sX
ANDX & XX
ORX0sX
ORX1s1s
ORXXX

Get Bit:

This method is commonly employed to determine the value of a bit at a specific position, denoted as 'i', within a given number, N. The approach involves performing a Bitwise AND operation between the given number and 2 raised to the power of i, which can be represented as (1 << i). If the resulting value is 1, it indicates that the bit at the ith position is set. Conversely, if the value is 0, the bit at that position is unset. This technique provides a straightforward way to ascertain the status of individual bits within a numerical value.

Set Bit:

This method is commonly employed to set a specific bit at a designated position, denoted as i, within the provided number N. The concept involves modifying the value of the given number N by performing a Bitwise OR operation between N and 2 raised to the power of i, which can be expressed as (1 << i). Upon evaluation, if the resulting value is 1, it signifies that the bit at the ith position has been set. Conversely, if the outcome is 0, it indicates that the bit at that particular position remains unset. This approach offers a direct and clear technique for determining the status of individual bits within a numerical value.

Clear Bit:

This method, known as "Clear Bit," serves the purpose of resetting the bit at a specific position (let's say i) within the provided number N. The concept involves modifying the value of the given number N by performing a Bitwise AND operation between N and the complement of 2 raised to the power of i, which can be denoted as ~(1 << i). Upon evaluation, if the resulting value is 1, it indicates that the bit at the ith position has been set. Conversely, if the outcome is 0, it signifies that the bit at that particular position remains unset. This systematic approach provides a straightforward and lucid method for ascertaining the status of individual bits within a numerical value.

Application of Bitwise Operator

  • Bitwise operations play a significant role in various fields such as embedded systems and control systems, especially in scenarios where memory management and data transmission efficiency are crucial aspects to consider.

  • In networking, bitwise operations are essential for minimizing data size by packing booleans together. These operations are instrumental in both combining and separating data efficiently through bitwise operations and shift instructions.

  • The application of bitwise operations extends to data compression and encryption, where these operations are fundamental for optimizing data storage and securing information.

  • Within graphics programming, older graphical user interfaces heavily rely on bitwise operations like XOR(^) for tasks such as selection highlighting and implementing overlays, showcasing the versatility and importance of bitwise operations in this domain.