Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detection of Negative Binary

Today in class my Computing teacher was explaining to us (or attempting to explain) how to write a negative binary number using Two's Complement. My question is this:

How does the end user determine the difference between 11101100 being 236 and -20? I know you can always check the most significant bit but is this always 100% accurate? Is it a convention of negative binary numbers to have the most significant bit indicate the sign?

Side note:
Why do we learn binary subtraction when we can just do:

Convert binary to denary -> subtract denary -> reconvert into binary

like image 733
Kezz Avatar asked May 10 '13 18:05

Kezz


People also ask

Is there a negative binary?

There are a few ways to represent negative numbers in binary. In normal decimal numbers we may simply place a negative sign ( - ) in front of the number to indicate that it is negative. In binray we don't have this luxury as we are limited to only 1's and 0's.

How do you know if a number is negative in 2's complement?

It's first (leftmost) bit is 1, which means that this represents a number that is negative. That's just the way that things are in two's complement: a leading 1 means the number is negative, a leading 0 means the number is 0 or positive. To see what this number is a negative of, we reverse the sign of this number.


1 Answers

Question 1:

"Is it a convention of negative binary numbers to have the most significant bit indicate the sign?"

There are multiple ways to represent negative numbers in binary. The most common is the two's-complement representation that you're learning about. In that system, yes, the highest-order bit will indicate the sign of the number (if 0 is grouped with the positive numbers).

In standard unsigned binary, numbers are represented by sequences of bits in positional notation (for brevity I'll only be using three bits):

b2b1b0 = 22b2 + 21b1 + 20b0 = 4b2 + 2b1 + b0

1112 = 710
1102 = 610
1012 = 510
1002 = 410
0112 = 310
0102 = 210
0012 = 110
0002 = 010

Two's-complement
There are several ways to look at 2s-complement, I think the answer is apparent in all of them. One way to get this system is to take the top half of the unsigned numbers (which all have the high bit set) and move them below zero:

0112 = 310
0102 = 210
0012 = 110
0002 = 010
1112 = -110
1102 = -210
1012 = -310
1002 = -410

You can clearly see that the high bit indicates the sign. Again, 0 takes up one of the 4 positive representations, which leads to the range not being symmetric: [3, -4] (though sometimes the most negative value is considered special, making the usable range symmetric). Equivalently, we can reinterpret the highest-order bit as a negative number:

b2b1b0 = -(22) b2 + 21b1 + 20b0 = -4 b2 + 2b1 + b0

Clearly, since the high bit has a bigger weight (in the sense of absolute value) than all the other bits combined, if it's set, the result is negative. If it's not set, all the remaining weights are positive and hence so is the result.

From this definition, we can derive the third interpretation: the commonly known rule that -a = ~a + 1 (where - means arithmetic negation, ~ means bitwise complementation, and we ignore overflow):

a + ~a = -4b2 + 2b1 + b0 + -4(~b2) + 2(~b1) + ~b0
a + ~a = -4(b2+~b2) + 2(b1+~b1) + (b0+~b0)
a + ~a = -4(1) + 2(1) + (1)
a + ~a = -1
a = -(~a + 1)
-a = ~a + 1

Here, we see that negation flips the high bit, so it indicates the sign of the number. Note that this is not strictly true, as the addition with one can flip the high bit back if all the other bits are set. However, this is only the case for 0 and the most negative number (-410, or 1002, in this case), both of which remain the same when negated.

The benefit in using 2s-complement is that the same hardware can be used to do signed and unsigned addition. This nice property does not hold for the other negative binary representations that have been used in the past, some of which I'll touch on briefly. Due to this fact, modern CPUs almost always use this representation for integer arithmetic (I'm not aware of any recent commercial counterexamples, but they may be out there). This is why you are learning about it (as opposed to Convert binary to denary -> subtract denary -> reconvert into binary): to understand how operations work at the gate level of an ALU.

One's-complement
1s-complement is closely related to 2s-complement. Negation is performed by inverting the bits only (no addition of 1). The leading bit still indicates sign, but there are different representations for positive and negative zero. I've never personally come across a real-world use of 1s-complement, but it's of historical interest.

b2b1b0 = -3b2 + 2b1 + b0

0112 = 310
0102 = 210
0012 = 110
0002 = 010
1112 = -010
1102 = -110
1012 = -210
1002 = -310

Sign-and-magnitude
Sign-and-magnitude is closest to how humans normally write negative numbers. The low two bits have the same weight as in the systems above and the high bit has no (additive) weight. Instead, it only changes the sign of the result. Here, obviously, the leading bit indicates sign. Like 1s-complement, there are two representations of 0. It is still used today in the mantissa of IEEE floating point numbers (although the exponent sits between the sign and the magnitude).

b2b1b0 = (-1)b2(2b1 + b0)

0 11 2 = + 3 10
0 10 2 = + 2 10
0 01 2 = + 1 10
0 00 2 = + 0 10
1 00 2 = - 0 10
1 01 2 = - 1 10
1 10 2 = - 2 10
1 11 2 = - 3 10

Excess-n
Excess-n is really more like a family of systems. All values are shifted up by n (known as the bias) and then represented as in the unsigned case. The leading bit may indicate the sign if the right bias is chosen, though with different polarity than the above systems (and 0 could be grouped with either the negatives or the positives). This is still used in the exponent of IEEE floating point numbers. For n = 3, the high bit does indicate sign and 0 is grouped with the negative numbers:

b2b1b0 = 4b2 + 2b1 + b0- n

1112 = 410
1102 = 310
1012 = 210
1002 = 110
0112 = 010
0102 = -110
0012 = -210
0002 = -310

Others
There are yet other, more esoteric, integer representations such as balanced-ternary, base-negative-2, or (arguably) binary coded decimal (or BCD for short). The reason I say BCD is arguable is that modern processors often still have support for it (though it's not how numbers are represented internally) and many calculators used to be based on it. In these systems, the leading bit (or trit, or base-n digit) may or may not indicate the sign (or may indicate it in some cases but not others).

Question 2:

"How does the end user determine the difference between 11101100 being 236 and -20?"

In general there's no way to tell whether a number stored in a register or memory is actually meant to be 2s-complement or unsigned, as pointed out by others. You essentially have to track what's done with it to determine that.

However, if the number is an immediate value stored directly in a machine code instruction, the opcode could indicate whether or not it's signed (depending on the architecture). This may change, for instance, how overflows are handled, or whether or not sign-extension is performed.

For example, there may be separate "load immediate" and "load signed immediate" instructions that copy an immediate value value into a larger register, the second doing sign-extension and the first not. "Branch" instructions often have a signed immediate to indicate the size of the jump (so that both forward and backwards branches can use a single instruction). There may be different "add immediate" and "add unsigned immediate" instructions that set overflow flags appropriately for the type of addition.

Sign extension
Sign extension means copying the high bit to preserve the value of a 2s-complement number. This will produce incorrect results for half the unsigned numbers.

Sign extension not performed:

1002 = 000001002
Unsigned: 410 = 410
Signed: -410 = 410

Sign extension performed:

1002 = 111111002
Signed: -410 = -410
Unsigned: 410 = 25210

0012 = 000000012
Signed and unsigned: 110 = 110

Overflow
Adding or subtracting two numbers may give a result that is too big (in an absolute sense) to be correctly represented. Addition of the same two binary sequences may cause overflow for signed numbers but not unsigned (or vice versa).

Signed overflows but unsigned does not:

0112 + 0112 = 1102
Signed: 310+310 = -210
Unsigned: 310+310 = 610

Unsigned overflows but signed does not:

1112 + 0102 = 0012
Unsigned: 710 + 210 = 110
Signed: -110 + 210 = 110

like image 134
jerry Avatar answered Oct 06 '22 00:10

jerry