Two's Complement: How Computers Represent Negative Numbers
Computers have no minus sign in their circuitry, so negative numbers are represented with a wraparound trick borrowed from something as ordinary as a car odometer.
A car's mechanical odometer only has so many wheels of digits. If it reads 000000 and something forces it backward by one mile, it can't display -000001 -- there's no minus sign on any of those wheels. Instead it rolls back around to 999999. Computers hit the identical wall with negative numbers: a fixed number of bits, no minus sign anywhere in the hardware, and a wraparound trick standing in for one.
A computer stores a whole number using a fixed number of bits -- say, 8 -- and every one of those bits is either a 0 or a 1. There's no separate symbol available for a sign, so representing negative numbers means finding some pattern of 0s and 1s that can stand in for "negative" without any extra character to spend on it.
Two's complement is the scheme nearly every computer settled on. To find the negative of a number, flip every bit (every 0 becomes a 1 and vice versa) and then add 1. The leftmost bit ends up doubling as a sign indicator -- 0 for positive, 1 for negative -- without needing to be read separately from the rest of the number. Counting downward from 0 in an 8-bit two's complement system, subtracting 1 from 00000000 doesn't error out; it wraps around to 11111111, the odometer rolling from all zeros to all nines.
The reason two's complement won out over earlier, more naive schemes -- like just reserving one bit purely as a plus-or-minus sign -- is that addition and subtraction circuits don't need any special-case logic for negative numbers. The same binary addition hardware that adds two positive numbers correctly adds a positive and a negative number and gets the right answer, wraparound and all, with zero extra circuitry. It also avoids the wasteful oddity of a separate "negative zero" that a plain sign-bit scheme creates.
This is also the missing piece behind a familiar bug: an integer that silently overflows past its maximum value doesn't crash or throw an error in many languages -- it wraps around, odometer-style, and can land on a large negative number instead of the expected positive one. Once binary and hex are comfortable, two's complement is the last piece that explains why -1, viewed through the wrong lens, looks like an enormous unsigned number instead of a negative one.
