How a bit pattern becomes a signed number
A hex value is really just a name for a fixed-width bit pattern — there's nothing in the bits themselves that says whether they represent a positive integer, a negative integer, a character, or something else entirely. The meaning comes from how the pattern is interpreted. Read as an unsigned value, 0xFFat 8 bits is 255. Read as a signed value using two's complement — the representation essentially every modern processor uses for signed integers — the same 8 bits mean -1. Nothing about the hex changes; only the interpretation does, and that interpretation depends entirely on the bit width you're assuming.
Why two's complement, specifically
Two's complement wasn't the only scheme computer designers considered. Sign-magnitude (a dedicated sign bit plus a magnitude, the way people write negative numbers by hand) and one's complement (simple bit inversion for negation) were both used in early computers. Two's complement won out because it lets a CPU use the exact same addition circuit for both signed and unsigned numbers — adding a negative number in two's complement produces the correct result without any special-casing for sign, whereas sign-magnitude and one's complement both require extra logic to handle signs correctly and both waste a bit pattern on a redundant representation of zero (positive zero and negative zero). Two's complement has exactly one representation of zero and gives one extra negative value that sign-magnitude schemes don't have room for.
The asymmetric range, explained
A signed 8-bit integer using two's complement ranges from -128 to 127 — not -127 to 127, and not -128 to 128. That asymmetry follows directly from the representation: with 8 bits there are 256 possible patterns total. Half of them (128 patterns) represent non-negative numbers, 0 through 127. The other half represent negative numbers, but because zero already used up one pattern from the "positive" half, the negative half gets one extra value at the bottom of its range: -128 through -1, which is 128 distinct values. The same logic scales to any width — a signed 16-bit integer ranges from -32,768 to 32,767, and a signed 32-bit integer from -2,147,483,648 to 2,147,483,647.
Why the bit width has to be specified
Interpreting a hex value as a signed integer only makes sense once a width is fixed, because the same hex digits mean different things at different widths. 0xFF is -1 as a signed 8-bit value, but as a signed 16-bit value the same bit pattern would need to be written 0x00FF, which is +255, not -1 — the top bit (the sign bit) is in a different position depending on the declared width. This is a frequent source of real bugs when reading a value out of a file format, network protocol, or binary struct with an assumed width that turns out to be wrong, or when a language implicitly widens or narrows an integer type during a cast.
A worked example across widths
Take the hex value 0x8000. As an unsigned 16-bit value, that's 32,768 — the top bit set, everything else zero. As a signed 16-bit value under two's complement, the same bits mean -32,768, the most negative value representable at that width, precisely because the top bit is the sign bit and every other bit is zero. Compare that to 0x7FFF, one bit pattern lower: unsigned, it's 32,767; signed, it's also 32,767, since the top bit is 0 and sign interpretation only changes values where that bit is set. That single-bit difference between the maximum positive value and the minimum negative value is exactly the asymmetry described above, made concrete.
Related tools for negative representations
This converter shows only the final signed value for a given hex bit pattern and width. If you want to see the derivation — how a negative decimal number is turned into its two's complement bit pattern step by step, through inverting bits and adding one — theTwo's Complement Calculator walks through that process explicitly. If instead you want ordinary sign-magnitude notation (a plain minus sign in front of a hex value, the way negative numbers are normally written by hand rather than how a CPU register stores them), the Negative Decimal ↔ Hex tool covers that case directly.
Overflow and range checking
A decimal value outside the representable range for a given width — 200 at 8 bits, for instance, which exceeds the signed maximum of 127 — can't be converted to a valid two's complement pattern at that width and is rejected here rather than silently wrapped or truncated. In real systems, what happens to out-of-range values depends entirely on the language and context: some languages raise an error or panic on signed overflow, others (including much of C and C++ for unsigned types, and Rust in release builds) silently wrap around, which is a well-documented source of bugs, including security vulnerabilities in code that doesn't validate bounds before an arithmetic operation.