How the representation works
Two’s complement is not a sign bit with a magnitude attached. It is modular arithmetic.
In an n-bit register, every value is taken modulo 2ⁿ. The top half of that range is read as negative — and because addition wraps at 2ⁿ anyway, that reading makes the arithmetic come out right with no special handling.
So 11111011 is 251 as unsigned and −5 as signed, and both are correct. The bits do not know which; the type does.
The flip-and-add-one recipe is a consequence rather than a definition: inverting gives 2ⁿ − 1 − x, and adding one gives 2ⁿ − x, which is exactly −x modulo 2ⁿ.
The asymmetry
An n-bit signed range is −2ⁿ⁻¹ to 2ⁿ⁻¹ − 1. There is one more negative value than positive.
The reason is that zero has to live somewhere, and it lives in the non-negative half. With 256 patterns, 128 go to the negatives and 128 to zero-and-the-positives — so the positives get 127.
The consequence is sharp: negating the minimum overflows. There is no +128 in an 8-bit signed register, so −(−128) comes back as −128. It is the one integer whose absolute value is negative.
This is a genuine and recurring source of bugs. `abs(INT_MIN)` is undefined behaviour in C. Java’s `Math.abs(Integer.MIN_VALUE)` returns a negative number and always has. Any code that negates a value it did not choose has to consider it.
Why not sign-and-magnitude
There are other ways to store a negative number. Two’s complement won, and for good reasons.
Sign-and-magnitude uses one bit for the sign and the rest for the value. It is the obvious design and it has two problems: there are two zeros (+0 and −0), and addition needs a comparator and a subtractor because the signs may differ.
One’s complement negates by inverting all bits. Also two zeros, and addition needs an end-around carry.
Two’s complement has exactly one zero, and ordinary binary addition works on signed values without modification. One adder handles everything, and subtraction is addition of a complement.
On a chip where every gate costs area and power, halving the arithmetic hardware settled the argument. It has been effectively universal since the 1960s, and the 2020 C++ standard finally made it the only permitted representation.
Overflow, and how quiet it is
When a value does not fit, it wraps. 127 + 1 becomes −128, and nothing complains.
That silence is the problem. In C, signed overflow is undefined behaviour — which does not merely mean the result is unpredictable, but that the compiler may assume it cannot happen and optimise on that assumption. A loop check written to detect overflow can be removed entirely, because the compiler reasons that overflow never occurs.
Unsigned overflow is different: it is defined to wrap, and can be relied upon.
Real consequences follow. The Ariane 5 lost a rocket in 1996 to a 64-bit float converted into a 16-bit signed integer that did not fit. Gandhi’s famous aggression in the original Civilization is a widely repeated story about an underflow that, by most accounts, did not actually happen — a reminder that the mechanism is real even where a particular anecdote is not.
This page wraps and flags, because that is what hardware does. It also says the wrap is silent, because a page that showed the wrap without saying so would be teaching half of it.
Where it gets used
Every processor. Signed integers in essentially every architecture in use are two’s complement, which is why the same bit patterns mean the same things across machines.
Reading dumps and protocols. A hex value from a register or a packet is a bit pattern; knowing the width and signedness is what turns it into a number.
Embedded work. Sensor readings and control values are often signed and narrow, so the range limits are close and overflow is a live concern rather than a theoretical one.
Debugging. A value that should be small appearing as four billion is almost always a signed pattern read as unsigned, and this page is how you check.
Sources and methodology
The representation is standardised; these are the references.
Method. The same bit pattern is reported under both readings, signed and unsigned, because that is what a register actually holds — a pattern, not a number, and the type decides which it means. Values outside the signed range are wrapped and flagged rather than refused, since wrapping is exactly what hardware does; the page says so and adds that the wrap is silent. The suite round-trips every one of the 256 signed 8-bit values through its bit pattern. That engine is verified on every change against 90 hand-written assertions, including that every 8-bit signed value round-trips through its bit pattern, and that negating the minimum gives back the minimum with an overflow flag. The count and the per-case breakdown are published on the formula verification page.
Read the guide
Two’s complement is modular arithmetic wearing a different name — the Modulo Calculator covers the underlying operation.