Binary Negative Space
This article is part of a series, access the series index.
As discussed in our article on understanding binary, in order for a computer to represent a binary number as less than zero we can’t just put a minus sign in front of it like we do with mathematics. Instead, we have to determine some way of encoding the negative number into the binary. This is tricky to understand exactly what that means, but I want to make sure you understand EXACTLY what that means. Let’s say you have an 8-bit (remember our binary article) ‘number’ representation. Remember that those 8 bits could be interpreted as any symbol, we just choose numbers as we can represent counting by ones and zeros. That being said those 8 bits could be a whole number or a signed number, we don’t really know until something else specifies that we’re going to interpret it as a signed number (capable of being less than zero). That is usually specified by the program being written for the computer. In conclusion then, just because you use a system to represent a negative number in binary doesn’t inherently make the binary number negative. There is no intrinsic meaning to a series of bits, just like there is no intrinsic value to objective objects and concepts.
The four most popular methods for encoding (representing) negative binary numbers are known as “sign and magnitude”, “ones’ complement”, “two’s complement”, and “Excess-K”. There are alternative methods as well that aren’t as popular such as negative binary where the number base itself is actually negative (being negative 2).
Sign A Magnitude
As previously mentioned in the binary article, the easiest way (in my opinion) to represent a signed integer in binary is simply assign a bit in the sequence to tell you whether that number is negative or not. For example, you would set it to one state (zero) for a positive number, and another state (one) for a negative number. That bit represents the “sign”. The rest of the sequence represents the “magnitude” which is easier to understand if you think of “magnitude” as “size” and “size” as “measurement” and “measurement” as “amount”…. leading to “number”. This is also known as the absolute value.
As written previously if you have an 8-bit number and you use the MSB (Most Significant Bit) as the “sign” (as is often the case) then you only have 7 bits left for the magnitude. With 7 bits you can represent up to the number, or magnitude, of 127.
What about zero? Well, there are two ways to represent zero. There is a positive zero and a negative zero. Wild huh? Let’s say you are using MSB 0 as you sign. In that case, zero can be represented as both 00000000, and 10000000, being positive zero and negative zero respectively.
On an advanced note, for anyone who knows, sign-and-magnitude is usually how the “significand” in “floating point” values is represented.
This concept requires the understanding of binary logic (another article).
Not mentioned in the binary logic article is that those boolean operations can be applied to a sequence of bits. When this happens it’s called a ‘bitwise operation’. You’ll find ‘bitwise operations’ in many programming languages including scripting languages. These programming languages include such examples as C, C++, C#, Java, Pascal, and so on.
In one’s complement representation of binary numbers, you have it that the negative representation of a positive number is the result of the bitwise NOT operator applied to the positive number.
As an example, the one’s complement form of 01001111 (79) is 10110000 (-79). It’s that simple (year, right). It’s called one’s complement because the negative form of a number can also be subtracted from from -0 (11111111 the one’s complement representation of zero.)
As an extra note zero can be represented in two ways in the one’s complement negative representation system: +0 – 00000000 and -0 – 11111111.
Two’s complement is another system that attempts to patch up the problems of one’s complement. In one’s complement there are two representations of the number zero, and when you add two numbers together there is a somewhat complex carry operation involved.
Two’s complement relies on one’s complement really, but ‘improves’ it somewhat. Put simply, a negative representation in two’s complement is one greater than the one’s complement representation of the same negative number. What that really turns into is two simple methods of generating two’s complement numbers
The first method involves a littler short-hand trickery. I don’t like to explain things from short-hand trickery as some others do because I don’t think it really explains the core premises. If all you see is short-hand trickery then you just know things by rote. However, I think I’ve explained the core of two’s complement enough so far that you can handle this.
Basically, you start with a particular bit sequence such as 101010. Then you do a bitwise NOT on all the bits to the left of the first 1 bit, so for example, you’d arrive at 010110. Why that is is that if you perform a bitwise NOT on 101010, you’ll get 010101… and if you add one you get 010110. Anything to the right of the first bit will be overridden by the addition of a bit.
Another way to look at it is to think of say 8 bits (though you can think of higher numbers). Eight bits will start at 0 (00000000) and proceed upwards to 127 (01111111), then you’ll hit -128 (10000000). That’s just the way -128 is. Then you get to -127 which is two’s complement of 01111111 -> 10000001.
There is only one zero – 00000000. This is because if you tried to produce a two’s complement of 0, you’d get in the first step 11111111, but when you add one, you’re back to 00000000.
There is also a simplification in one’s complement addition (which I didn’t really go into). To add two two’s complement numbers, you just add them as if you’d add them like they were positive numbers. Easy-peesy.
Excess-K (also known as Excess N) is simply an offset, called a bias. The K (or N) stands for the amount of the bias. What does bias mean? It basically means that any number’s negative representation is the bias added to that number. This makes zero represented by the bias, and 00000000 represents the bias in negative. This is all done, as I understand it, in accordance with the number of bits that would be required to represent the bias. In this way, the MSB (Most Significant Bit) carries the sign information, much like in the sign-and-magnitude method.
In order to add two numbers in Excess-K, you have to through some arithmetic. I found this interesting so I’ll share it with you. Take it that you have A, B, and C. The arithmetic is as follows: A + B = C + K, and thus C = (A + B) – K.
Excess-K is generally used in floating point representations of the exponent of the number. If you want a double precision exponent you’d use an 11-bit Excess-1023 binary representation.
Negative Binary Really
Now, there’s what’s known as base -2. Remember back when I discussed binary I talked about how it was really base 2? That powers of 2 were the place values of binary numbers? Well, in base -2, negative two is the base of the number system. Here’s a diagram of what I mean:
The thing about base -2 is that its ability to represent numbers is lopsided. If there are an even number of bits the largest representable negative number is twice the size of the highest possible positive value, and if there is an odd number of bits the reverse is true: the largest representable positive number is twice the size of the absolute value of the lowest possible negative value. I’ll leave it to you the reader to work that one out.
That’s it, folks! There are many ways to represent negative binary numbers. None of them is necessarily ‘better’ than the others although I’m sure microprocessor engineers would disagree with me. Many times a particular representation is chosen because that’s what can be easily built for a particular microprocessor. When you program in assembly language, which is as close to the processor level as a programmer can usually get, you have to make sure you know whether you’re dealing with a signed representation (possibly negative) or an unsigned representation. Sometimes there are flags in the microprocessor that will tell you, but do remember that any series of bits can be interpreted as a signed value (possibly negative).
If you appreciate my tutorials please help support me through my Patreon.