What are complements ?

Complements are way to store negative numbers and manipulate them in binary.

Why complements ?

Representing negative numbers in binary was a real hassle ! That’s were complements help to store signed numbers as binary.

But it was not always like that.


1. Sign-Magnitude

First idea of representing signs:

0 = + and 1 = -, followed by the number in binary !

00000101 = 5 10000101 = -5

❌ Problem with sign-magnitude

  • Two representation of 0 -> 00000000(+0) and 10000000(-0) .
  • Calculation difficult for the CPU !
int a = +0;
int b = -0;

// ambigious, depends on compiler.
// Even though this prints "Equal", internally +0 and -0 may be stored differently,
// which makes operations more complex and ambiguous at the binary level.
if(a == b){
	std::cout << "Equal" << std::endl;
}

Two values of 0 will cause issue because if the compiler considers signed then its not equal else they are equal. So there must be 256 unique values.

So 1’s Complement came in…


2. 1’s Complement

1’s Complement said rather than using a sign bit we flip the whole number to get its negative !

00000101 = 5 11111010 = -5

We flip the bits ! We get the negative part ! But this was also not the best solution

❌Problem with 1’s Complement

1’s Complement had the same issues.

  • Similar 0 values !
  • Harder arithmetic for CPU to perform.

00000000 = +0 11111111 = -0

But 2’s complement solves this issue


3. 2’s Complement

This new complement method just solves the issue the others weren’t able to do ! 2’s complement adds 1 to the 1’s complement of a number to get its negative.

00000101 = 5 11111010 = ~5 (1’s complement) 11111011 = -5 (2’s complement) (Needed Negative Number as binary)

How is it working ?

So the logic is the range ! 2’s complement is for signed integers therefore it ranges from -128 to +127.

The MSB acts as a negative weight (−128 in 8-bit systems) — it’s not just a flag but part of the actual value. For example:

2’s Complement for 5 to get -5 : 00000101= 5; 11111011 = -5 (2’s Complement)

1     1     1     1     1     0     1     1  #<-(-5)

-128 + 64 + 32 +  16  + 8  +  0  +  2   +  1 = -5

If the first bit is 0then its a positive Number !

IT LOOKS LIKE BLACK MAGIC !

💡 How it solves dual 0 representation

Lets just look at representation for 0:

00000000: 0 11111111: -1 (This was -0 for 1’s complement and sign-magnitude)

Key observation: If the first bit is -128 won’t we encounter +128 and have the same issue ?

🤔 Isn’t there a clash when we arrive at a mirrored value ?

Yes there would have been a clash…but…there is no +128 in 2’s Complement as the bit required to get +128 is reserved by -128 so the highest we can get to is +127 i.e. 64 + 32 + 16 + 8 + 4 + 2 + 1 (7 bits) and the MSB is 0 if its 1 then it becomes -128 therefore we will have -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 which is -1 !

This is how computers store signed numbers, Both Positives and Negatives !