Two’s complement is the dominant way computers store signed integers. It lets a single set of adder circuits handle both signed and unsigned arithmetic and gives a unique representation of zero. This converter shows the exact bit pattern for any signed integer at any of the common CPU widths: 4, 8, 16, 32, or 64 bits.
How it works
For a width of W bits the signed range is -2^(W-1) to 2^(W-1) - 1. To encode a value:
- If the value is non-negative, write it in plain binary, zero-padded to
Wbits. - If the value is negative, the stored pattern is
2^W + value. A practical recipe: take the magnitude in binary, invert every bit, then add 1.
Decoding reverses this: if the top (sign) bit is 1, subtract 2^W from the unsigned reading to recover the negative value.
Step-by-step example
Encode -42 in 8 bits:
Magnitude 42 = 0010 1010
Invert all bits = 1101 0101
Add 1 = 1101 0110 → 0xD6 → 214 unsigned
Check: 214 − 256 = −42 ✓
The same byte 0xD6 means 214 when the type is uint8_t, or -42 when the type is int8_t. The bits are identical — only the interpretation changes. This is called type punning and is a common source of bugs when casting between signed and unsigned types in C/C++.
Why 4-bit is included
4-bit two’s complement is used in educational contexts and in some embedded nibble registers. Its range is -8 to +7. Seeing the same algorithm at 4 bits makes the bit patterns easy to see in full, which is useful when first learning the encoding.
When to use each width
- 8-bit (int8_t): sensor readings, small counters, raw bytes with sign interpretation
- 16-bit (int16_t): audio samples, older protocol fields, small coordinates
- 32-bit (int32_t): the default signed integer in most languages; indices, IDs, timestamps pre-2038
- 64-bit (int64_t): file offsets, monetary amounts in minor currency units, Unix timestamps post-2038
The overflow quirk: the most negative number has no positive counterpart
Two’s complement’s asymmetric range produces one unusual case at every width: the most negative value (-128 at 8 bits, -32768 at 16 bits, and so on) has no corresponding positive value within the same width. Negating it with the invert-and-add-one recipe produces the same bit pattern — the number wraps back to itself. This is why abs(INT_MIN) is undefined behaviour in C and why languages with overflow checking throw an exception for -(Int.min) in Swift. The converter shows this when you enter the minimum value for a chosen width.
Notes
The tool uses BigInt internally, so 64-bit values are computed exactly without floating-point rounding — JavaScript’s Number can only represent integers exactly up to 2^53, which is not enough for full 64-bit signed arithmetic. If you enter a number outside the signed range for the chosen width, the tool shows the valid range rather than silently wrapping.