Problem
Add two positive numbers without using + or ++ but only bitwise operators.
Solution
Video explanation
Here is the video explaining below methods in detail. Please check it out:
Method 1 - Iterative Half Adder - Using & and ^ Operator
To solve this problem, we rely on two fundamental bitwise operators: &
(AND) and ^
(XOR).
- The
&
operator is responsible for determining the carry bits. - The
^
operator performs the addition of two numbers excluding the carry, effectively functioning as a simple addition without overlaps.
For two bits, their sum can be computed using the XOR ^
operator, while the carry is derived by applying the AND &
operator on the same bits. This concept mirrors the fundamental functioning of a Half Adder, a circuit that combines these operations to add two single bits.
We can expand this logic further to work with integers:
- If two numbers,
x
andy
, do not share set bits in the same positions, the XOR operation (x ^ y
) gives us their sum. - To handle the positions where both numbers have set bits (i.e., generate a carry), the AND operation (
x & y
) identifies all the carry bits. Shifting these carry bits left by one position ((x & y) << 1
) aligns them correctly for the addition process.
By combining these two results—x ^ y
for the sum and (x & y) << 1
for the carry—we iteratively compute the final sum. This approach is directly inspired by the core principles of a half-adder.
The key idea is to break down the problem into two parts: sum without carry and carry itself. For example, let’s take the binary representations of 2
and 1
(10
and 1
). Since no carry is required to add these numbers, their sum can be directly calculated using the XOR (^
) operator:
|
|
Step by Step Logic for Decimal Numbers
- Start by adding
759
and674
while ignoring any carry. The result is323
. - Now add
759
and674
while only accounting for the carry. This gives1110
. - Add the results from the first two steps recursively, continuing until no carry remains:
1110 + 323 = 1433
.
This method can be adapted for binary numbers.
Adapting logic for binary numbers
Now, how would we do this in binary?
- When adding two binary numbers without a carry, the resulting bit at position
i
will be0
if both bits at that position ina
andb
are either0
or1
. This corresponds to the XOR (^
) operator. - When adding two numbers and considering only the carry, there will be a
1
at a positioni
only if both bits at positioni-1
ina
andb
are1
. This is equivalent to the AND (&
) operator, followed by a left shift to account for the carry moving to the next higher position ((a & b) << 1
). - Repeat the above operations until no carry remains.
Breaking down the operations
Get the Carry
To calculate the carry for two numbers, a & b
identifies all positions where both numbers have 1
bits. Left-shifting this result by one bit ((a & b) << 1
) gives the carry:
- Example: Adding
3
(011
) and2
(010
) results in:- Carry =
(a & b) << 1
:010 << 1 = 1 0
(binary) or2
(decimal).
- Carry =
Get the Sum Except Carry
- Carry =
(a & b) << 1
:010 << 1 = 1 0
(binary) or2
(decimal).
Example - Add 13 and 10 in Binary
Let a = 13
and b = 10
in binary:
Binary Representation
Let a = 13
and b = 10
in binary:
|
|
Using ^ and &
Now we can break the addition into two parts, one is simple addition without taking care of carry, and other is taking the carry.
1) Sum Without Carry
Use XOR (^
) to add without handling the carry:
|
|
2) Carry
Use AND (&
) to identify positions for carry, then left-shift by one bit:
|
|
|
|
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n)
, wheren
is the number of bits in the larger of the two numbers. This is because, in each iteration, at least one higher-order bit ofb
becomes0
. In the worst-case scenario, it takesO(n)
iterations to reduceb
to0
. - 🧺 Space complexity:
O(1)
, since no additional space is required apart from a constant number of variables (a
,b
,carry
) used during the computation.
Method 2 - Recursive Half Adder
Same approach, but recursive
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n)
, wheren
is the number of bits in the larger of the two numbers.The recursion depth depends on the number of bits in the input numbers. Similar to the iterative solution, there are at mostO(n)
recursive calls - 🧺 Space complexity:
O(n)
. Each recursive call consumes stack space. In the worst case, there will beO(n)
recursive calls