Why negative numbers need a trick
A register is just a row of bits. To store −5 we have to agree on which bit pattern means −5. The method that won is two’s complement, because it lets the CPU use one adder for positive and negative numbers alike.
The weights idea
In an 8-bit unsigned number the bit weights are 128, 64, 32, 16, 8, 4, 2, 1. In two’s complement the leftmost weight becomes negative: −128, 64, 32, 16, 8, 4, 2, 1.
So 11111011 = −128 + 64 + 32 + 16 + 8 + 2 + 1 = −5.
Negating a number
to get −x:
1. write x in binary (n bits)
2. invert every bit (one's complement)
3. add 1
Example: −37 in 8 bits
| Step | Bits |
|---|---|
| 37 in binary | 00100101 |
| Invert | 11011010 |
| Add 1 | 11011011 |
Check: −128 + 64 + 16 + 8 + 2 + 1 = −37.
Range
With n bits you can store −2ⁿ⁻¹ to 2ⁿ⁻¹ − 1. For 8 bits that is −128 to 127, and for 4 bits −8 to 7. There is only one zero (0000), which is why the range is not symmetric.
Subtraction for free
To compute a − b the CPU adds a to the two’s complement of b. No separate subtractor is needed, only the adder shown in the ripple-carry adder lesson.
Code
def twos_complement(x, bits=8):
return format(x & ((1 << bits) - 1), f'0{bits}b')
def from_twos_complement(s):
n = len(s)
value = int(s, 2)
return value - (1 << n) if s[0] == '1' else value
print(twos_complement(-37)) # 11011011
print(from_twos_complement('11111011')) # -5
Common mistakes
- Forgetting to add 1 after inverting. Inverting alone gives the one’s complement, which is off by one.
- Using too few bits. −37 does not fit in 6 bits (range −32 to 31).
- Treating the sign bit as “just a minus sign”. It is a bit with weight −2ⁿ⁻¹, and the other bits change meaning too.
- Mixing up the range: −128 exists in 8 bits, but +128 does not.
Complexity at a glance
| Case / operation | Time | Why |
|---|---|---|
| Negate a number | O(n) | Invert n bits and add 1, which may ripple a carry through all n bits. |
| Add or subtract | O(n) | The same adder works for signed and unsigned numbers. |
| Extra space | n bits per number |
Quick check
Test yourself — pick an answer to see if you got it.
1. What is the 8-bit two's complement representation of −5?
5 = 00000101. Inverting gives 11111010, and adding 1 gives 11111011.
2. What range of values can an n-bit two's complement number hold?
There is one more negative value than positive ones, because zero uses a pattern from the non-negative half.
3. What weight does the leftmost bit have in an 8-bit two's complement number?
The sign bit counts as −2ⁿ⁻¹. For 8 bits that is −128, and the other bits add positive powers of two.
4. Why do computers prefer two's complement over sign-magnitude?
Addition and subtraction work with the same circuit, and there is only one zero.