A Gentle Introduction to Signed Integer Representation
Introduction
When we talk about numbers and data types in programming we generally mention how many bytes they occupy in memory. For example, we say that 32 bit integer can hold values from 0 up to 232-1, 64 bit can hold up to 264 - 1 and etc. However, this examples are true when the integer is unsigned, which means that it consists of only positive numbers. In signed integers, the ones that hold both negative and positive values, the minimum and maximum values are different: 32 bit signed integers can hold values from -231 up to 231-1. Why? To understand it deeply, let see it visually.
Unsigned integers in binary
Let’s say we have a 4 bit unsigned integer. Its mimimum value is 0 when the maximum value is 15. Let’s write them all down:
0000 -- 0 in decimal, this is the minimum |
This is pretty clear and an usual way of how we think of binary representation of integers. What about negative numbers? If 4 bit integer was signed then its minimum value would be -8 (-23) when the maximum value would be 7(23-1). Again why? Let’s write them down:
0000 -- 0 in decimal |
Now, this looks quite confusing, right? One question you may ask is: Why is 1111 is -1 and 1000 is -8?. Now, if you add -7 and 7 or -1 and 1 or -5 and 5 in binary, you will see that you get 0 in binary (in 4 bytes, ignore the carry). Why this works? Is it a magic? To understand it clearly we need to understand complements technique. The reason, why negative 1 is 1111, because 1111 is 2’s complement of positive one (0001). So, what is complement technique?
Complement tehcnique
Let’s first begin with the decimal world. If we want to find 9’s complement of any decimal number, we subtract it from all 9’s. For example, if we want to find 9’s complement of 58, we subtract 58 from 99:
99 - 58 = 41 --> is 9's complement of 58
If we add 1 to 41, we will get 42 and that will be 10’s complement. So, adding 1 to the 9’s complement gave us 10’s complement. This is simply, subtracting 58 from 10.
99 - 58 + 1 = 42 --> is 10's complement of 58
Similarly, if we want to find 2’s complement of any binary number, we subtract it from all 1’s to find 1’s complement and add 1 to it to get 2’s complement. So, 1’s complement of 1001 is: 1111 - 1001 = 0110
and adding 1 to it will give us 2’ complement: 0110 + 0001 = 0111
. But, how computers subtract a number from the other?
If you were careful, you would notice that to find 1’s complement of binary number we don’t need to practically subtract the number from 1111. Just flipping the bits would give us the right answer, so instead of subtracting, we could apply logical NOT operator to the number: NOT 1001 = 0110 --> 1's complement of 1001
Subtracting using complement
Since there is no subtraction operation in computers, we also need to subtract numbers using addition. Luckily, complement technique also helps here.
Again in the decimal world! Let’s say we want to subtract 58 from 87. 10’s complement of 58 is 42, and if you add 87 and 42 together it will give you 129. Remove, 1 from 129 (because we are only working with 2 digits and ignoring the overflows) and you will get 29. Guess what? 87 - 58 is 29.
Similarly, in binary world, if you want to subtract a number from another, find 2’s complement of the small number and add it with the other. For example, to calculate 1100 1011 - 1001 1100
, (203 - 156 in unsigned representation) find 2’s complement of 1001 1100
which is NOT 1001 1100 + 0000 0001 = 0110 0011 + 0000 0001 = 0110 0100
and then adding it with the first number will give us 1100 1011 + 0110 0100 = 010010 1111
. Since we ignore overflows, we will ignore first two digits of the result and our result will be 0010 1111
which is 47 in decimal (203 - 156 = 47).
Conclusion
Now, hopefully it makes sense why the negative numbers were depicted in the way they are. And as you already understood from the examples above any signed integers minimum value will be -2n-1 and maximum value will be 2n-1-1. If anyone asks you what is, let’s say negative 8 in binary, just find what is positive 8 in binary, then two’s complement of that number will be negative 8.
The contents of this article is heavily based on Number Theory for Programmers course on Udemy, so I highly recommend you to enroll and learn more.
Thanks for reading.
If you find any mistakes on article, please let me know.