CE2704 · Digital Logic Design
Theme 1 · Numbers & codes

Two's complement & signed numbers

There is no minus-sign wire inside a chip. This is how negatives are encoded in bits — the scheme every modern CPU uses, because the same adder just works.

Built from first principles. (The MPU6050 reports its accelerometer and gyro readings as 16-bit two's-complement values.)

Before you start

What you need first

  • Base conversions — reading binary by place value.
  • Binary addition — the flip step ends with "add 1", and the sanity-check is a binary sum.

What you'll be able to do

  • Negate a number in two's complement (flip + add 1).
  • Read any two's-complement value, positive or negative.
  • State the range for a given width and recognise signed overflow.

How do we store a negative number?

So far our binary numbers have been unsigned — zero and positive only. But engineering is full of negatives: a sensor reading −40 °C, signed g-force, an audio sample swinging below zero, the difference of two readings.

Inside the chip there is still only 0 and 1 — no minus-sign wire. So the sign must be encoded in the bits. Three schemes were tried historically; the third one won.

SchemeIdeaVerdict
Sign-magnitudeMSB = sign, rest = magnitudeTwo zeros (+0, −0); messy addition
1's complementNegate by flipping every bitStill two zeros; "end-around carry" quirk
2's complementFlip, then add 1One zero; the same adder just works

Two's complement — how to negate

To get the representation of a negative number, do two steps:

  1. Flip every bit (0↔1 — this is the 1's complement).
  2. Add 1.
📐 Worked example

Negate +5 in 8 bits

1Start from +5, then flip every bit:
$$ 00000101 \;\xrightarrow{\text{flip}}\; 11111010 $$
2Add 1:
$$ 11111010 + 1 = 11111011 $$
So −5 = 11111011 in 8-bit two's complement.
Intuition: we're really computing \(2^n - x\). When you add that to \(x\) you get \(2^n\), which overflows into the discarded carry bit, leaving 0 — exactly what \(x + (-x)\) should give.

✏️ Try it yourself

Convert −7 to 8-bit two's complement.

+7: 00000111. Flip: 11111000. Add 1: 11111001. Answer: −7 = 11111001.

Why two's complement is brilliant

Sanity check: +5 + (−5) should be 0.

$$ 00000101 + 11111011 = 1\,00000000 $$

The 9th bit is the carry-out; in 8-bit arithmetic it is simply discarded. What remains is 00000000 = 0. ✓

Only one zero. +0 and −0 are the same pattern (00000000) — no "two zeros" headache.
Addition just works. One adder handles positives and negatives — no special sign hardware. A huge win in silicon, and why every CPU since the 1970s uses it.

The range of values

For an \(n\)-bit two's-complement number the MSB still signals the sign (0 = positive, 1 = negative), and the range is asymmetric — one extra negative value:

$$ -2^{\,n-1} \;\;\text{to}\;\; +2^{\,n-1}-1 $$
WidthSigned rangeUnsigned range
8-bit−128 … +1270 … 255
16-bit−32768 … +327670 … 65535
32-bit−2147483648 … +21474836470 … 4294967295

Reading a two's-complement value

Always check the MSB first.

📐 Worked example — positive

What value is 00001101?

MSB is 0 → positive → read it as ordinary binary:

$$ 00001101 = 8 + 4 + 1 = +13 $$
📐 Worked example — negative

What value is 11110011?

MSB is 1 → negative → negate it (flip + add 1), read that, put the minus back:

1Flip, then add 1:
$$ 11110011 \xrightarrow{\text{flip}} 00001100 \xrightarrow{+1} 00001101 $$
2Read 00001101 = 13, then restore the sign:
$$ 11110011 = -13 $$
Same bits as +13 mirrored — negating a negative gives its positive size.

✏️ Try it yourself

What decimal value is 11110001, read as 8-bit two's complement?

MSB = 1 → negative. Flip + 1: 11110001 → 00001110 → 00001111 = 15. Answer: 11110001 = −15.

Signed overflow — a real source of bugs

If a result won't fit the width, it wraps:

$$ 01111111\,(+127) + 00000001\,(+1) = 10000000\,(-128) $$

We wrapped from +127 straight to −128.

Real failures from integer overflow:
  • Ariane 5 (1996): rocket destroyed 39 s after launch — a 64-bit float forced into a 16-bit signed integer overflowed.
  • Boeing 787: needed a reboot every 248 days — a 32-bit signed counter ticking every 10 ms overflowed (\(2^{31}\) ticks × 10 ms ≈ 248 days).
Engineer's job: pick a data type wide enough for the worst case, decide what happens at the limit (saturate? wrap? error?), and test the boundary on purpose.

Recap — the whole topic on one screen

IdeaWhat you own now
NegateFlip every bit, then add 1
ReadMSB 0 → read as binary; MSB 1 → negate, read, add minus
Range (n-bit)\(-2^{n-1}\) … \(+2^{n-1}-1\) (8-bit: −128…+127)
Why it winsOne zero; the same adder handles + and −
OverflowResult wraps; choose a wide-enough type

Next topic

Beyond integers: fixed & floating-point

Integers (signed and unsigned) are sorted. But how does a machine store fractions like 6.625 or huge numbers like \(10^{24}\)? Next: fixed-point and IEEE-754 floating-point.

→ Beyond integers: fixed & floating-point