Understanding two’s complement2 min read

Have you ever wondered why, in Java and other languages, one byte can only represent \(-2^7\) to \(2^7-1\) as the maximum value and why cannot we have \(2^7\). There is indeed a reason for that, in Java, some primitive types (int, short, long, byte) are signed two’s complement. In this article, we will learn how two’s complement can be used to represent both positive and negative decimal values in the binary representation.

Given a positive number, two’s complement is an operation to reverse this number into a negative number, and the most significant bit (the leftmost one) indicates whether this number is positive or negative (0 means positive, and 1 means negative). For example, I have the number 7 and want to find the binary representation of its negative, i.e. -7. Here is the general procedure (to make it less verbose, we only use 4 bits to represent our binary number):

  • Get the binary representation of the number 7 => \(0111_2\)
  • Flip all the bits (0 becomes 1 and 1 becomes 0) => \(1000_2\)
  • Add 1 to the flipped value => \(1001_2\)

That’s how you get the number -7 in its binary form. Along the way, we have the number 7 with the binary value of \(0111_2\) since it’s two’s complement value, we need to add an extra 0 at the most significant bit to signify it’s a positive value.

Here, to verify that 1001 is indeed -7 in the decimal format, we don’t calculate the decimal representation as we usually do, but instead, we will add all the bits up but subtract the most significant bit:

\(-2^3 * 1 + 2^2 * 0 + 2^1 * 0 + 2^0 * 1 = -8 + 1 = -7\)

Now we have some knowledge of how two’s complement works, we can come back to the initial question of why Java can only represent 127 as the maximum value instead of 128 for the byte data type. Because each byte contains 8 bits and bytes in Java are two’s complements, meaning that we have to reserve 1 bit for the sign, and the rest 7 bits represent the magnitude, here \(11111111_2\) will represent -1, not 128. Going backward, we can still represent -128 as the lower bound as we know \(10000000_2\) is indeed -128.

To find the decimal representation of any two’s complement value, we can use this general formula:

\(w = -a_{N-1} 2^{N-1} + \sum_{i=0}^{N-2} a_i 2^i\)

Or if the formula above looks complicated, we also can use this procedure to compute the decimal value for a two’s complement; let’s say we want to convert \(1100_2\) to decimal:

  • First, we find the complement of \(1100_2\) by flipping all the bits, which is \(0011_2\)
  • Add one to it, \(0100_2\)
  • Convert \(0100\) to decimal, which is 4
  • Apply the sign that we have at the beginning; the result we get is -4.
0 0 votes
Article Rating
Previous Article
Next Article
Subscribe
Notify of
guest
0 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Every support is much appreciated ❤️

Buy Me a Coffee

0
Would love your thoughts, please comment.x
()
x