Digital Logic Toolkit — Two’s complement
Two's Complement Converter
Signed binary at the width you choose — with the complement chain, the range, and what happens when it overflows.
Width
8-bit signed range: -128 to 127 · unsigned range: 0 to 255
Value
Binary
Two’s complement is ordinary positional notation with one change: the most significant column’s weight is negative.
Signed (two's complement)
-45
Unsigned
211
Hexadecimal
D3
Octal
323
-45 in 8-bit two's complement
Encode -45 in 8-bit two's complement. Representable range: -128 to 127.
|-45| in binary00101101
invert every bit11010010
add 111010011— invert-and-add-one is the negation rule
8-bit pattern110100110xD3
check11010011 reads 211 unsigned and -45 signed
Decode 11010011 as 8-bit two's complement
bit string110100110xD3
unsigned reading211— straight positional value of the bits
sign bit1— set, so the value is negative
211 - 2^8-45
The three signed systems, side by side
-45 in three signed systems (8 bits)
| system | bits | range | zero encodings |
|---|---|---|---|
| two's complement | 11010011 | -128 to 127 | 1 |
| one's complement | 11010010 | -127 to 127 | 2 |
| sign-magnitude | 10101101 | -127 to 127 | 2 |
Only two's complement adds without correction; one's complement needs an end-around carry, which is the same mechanism as the Internet checksum.
Sign extension and zero extension
Extend 11010011 from 8 to 16 bits
sign bit1— replicated 8 times to the left
| extension | bits | value |
|---|---|---|
| sign | 1111 1111 1101 0011 | -45 |
| zero | 0000 0000 1101 0011 | 211 |
Zero extension changes the value from -45 to 211: it is only correct for unsigned data.
Truncation to a narrower word
Truncate 11010011 to 4 bits
discarded1101
kept0011
value-45 -> 3
A discarded bit differs from the new sign bit, so the value changed.
Negating this value
Negate 11010011
start11010011— = -45
invert every bit00101100
add 100101101— = 45
Shortcut: copy the bits from the right up to and including the first 1, then invert everything to the left.
Notation used on this page
- The most significant bit is leftmost. Bits are 0-indexed from the least significant end, so bit 0 is the rightmost.
- The most significant bit is called the sign bit, but it is a value bit with weight −2^(w−1), not a separate flag.
- Hex output is upper case with no 0x prefix inside the bit strip.
Start from a worked example
What two's complement is
Two’s complement is ordinary positional notation with one change: the most significant column’s weight is negative. At eight bits the place values read −128, 64, 32, 16, 8, 4, 2, 1, so 11010011 is −128 + 64 + 16 + 2 + 1 = −45. That is the definition, and every other rule on this page follows from it.
The familiar “invert the bits and add one” procedure is a consequence, not the definition. Inverting a w-bit pattern turns x into 2^w − 1 − x, and adding one turns that into 2^w − x, which is exactly the pattern whose negative-weighted sum is −x.
Converting a negative decimal to two's complement
Write the magnitude, invert every bit, add one. For −45 at eight bits: 45 is 00101101; inverted it is 11010010; plus one it is 11010011.
The by-hand shortcut gives the same answer with no addition: copy bits from the right up to and including the first 1, then invert everything to the left. 00101101 → keep the final 1, invert 0010110 → 1101001 → 11010011.
Converting two's complement back to decimal
Courses teach two methods and both are correct, so both are shown here.
- Weighted sum. Add the place values of the set bits with the most significant one negative: −128 + 64 + 16 + 2 + 1 = −45.
- Negate and read. If the most significant bit is 1, apply invert and add one to get the magnitude, then attach the minus sign:
11010011→00101101= 45, so the value is −45.
Width and range
A two’s-complement value is meaningless without a width. 1011 is −5 in 4 bits and 11 in 8 bits. At w bits the signed range is −2^(w−1) to 2^(w−1)−1 and the unsigned range is 0 to 2^w−1.
| Width | Signed range | Unsigned range |
|---|---|---|
| 4 | −8 to 7 | 0 to 15 |
| 8 | −128 to 127 | 0 to 255 |
| 16 | −32768 to 32767 | 0 to 65535 |
| 32 | −2147483648 to 2147483647 | 0 to 4294967295 |
| 64 | −9223372036854775808 to 9223372036854775807 | 0 to 18446744073709551615 |
Sign extension and truncation
Widening a signed value copies the sign bit into the new positions. 1011 at 4 bits is −5; sign-extended to 8 bits it is 11111011, still −5. Zero-extending it instead gives 00001011 = +11, which is correct only if the value was unsigned. For a positive source the two agree: 0110 becomes 00000110 = 6 either way.
Truncation preserves the value only if every discarded bit equals the sign bit that remains. 11111011 (−5) narrowed to four bits is 1011 = −5, which is safe. 11110110 (−10) narrowed to four bits is 0110 = +6, which is not.
Overflow
Signed overflow has two equivalent tests. It occurs exactly when the carry into the most significant column differs from the carry outof it — that is, V = c_w ⊕ c_(w−1). Equivalently, it occurs when both operands have the same sign and the result’s sign differs from theirs.
The classic exam pair, both at eight bits: 0x7F + 0x01 = 0x80 sets V = 1 with C = 0 — overflow without a carry — while 0xFF + 0x01 = 0x00 sets C = 1 with V = 0 — a carry without overflow. The full ripple, with both flags on every result, is on the binary arithmetic page.
The −2^(w−1) asymmetry
At eight bits 10000000 is −128. Invert it and you get 01111111; add one and you are back at 10000000. −128 has no positive counterpart in eight bits, so negating it returns itself. This is the one asymmetry of two’s complement and it is the reason abs(INT_MIN) overflows in C, Java, C# and Rust.
Sign–magnitude and one's complement
Three conventions for signed binary were in use, and two of them lost for the same two reasons: they have two representations of zero, and their adders need a correction step.
| System | −5 in 8 bits | Range | Zeros | Addition |
|---|---|---|---|---|
| Sign–magnitude | 1000 0101 | −127 to +127 | two (00000000, 10000000) | needs a sign and magnitude case analysis |
| One's complement | 1111 1010 | −127 to +127 | two (00000000, 11111111) | needs an end-around carry |
| Two's complement | 1111 1011 | −128 to +127 | one | plain binary addition, unmodified |
The end-around carry that one’s-complement addition needs is not a museum piece: it is exactly the fold the Internet checksum uses, which is the same end-around carry on the parity and checksum page.
Where the boundary is: floating point
Two’s complement is for integers. Non-integers use IEEE 754, which stores a sign bit, a biased exponent and a significand instead of place values. −118.625 as binary32 is 0xC2ED4000: the sign bit is 1, the biased exponent 10000101₂ is 133, so e = 133 − 127 = 6, and 1.110110101₂ × 2⁶ is −118.625. The standard is IEEE 754-2019 (opens in a new tab).
Notation used on this page
- The most significant bit is leftmost; bits are 0-indexed from the least significant end.
- The most significant bit is called the sign bit, but it is a value bit with weight −2^(w−1), not a separate flag.
- Hexadecimal output is upper case with no
0xprefix inside the bit strip. - Two’s complement has exactly one zero, so −0 is normalised to 0.
Sources
Two’s complement has no single canonical citation and is stated here as the standard result it is. The one external standard cited is IEEE 754-2019, IEEE Standard for Floating-Point Arithmetic (opens in a new tab), in the floating-point section above.
Worked examples
- −45 in 8-bit two's complementintroinvert and add one
- 1011 0101 read as a signed 8-bit valueintrothe leading 1 means negative
- The most negative 8-bit valuecorethe asymmetric range
- +127 and the sign-bit boundarycoreone more and it wraps
- Overflow: 100 + 100 in 8-bit signedcorecarry out is not overflow
- Sign extension: 1011 from 4 bits to 8examcopy the sign bit, do not pad with zeros
- −1 at 8, 16 and 32 bitsexamall ones at every width
- −1000 in 16-bit two's complementedge casea value that needs more than a byte