Two's complement calculator

Enter a decimal number to see its two's complement bits, or enter a hex or binary pattern to see what number it is signed and unsigned. The page shows the invert-and-add-one steps, a clickable bit grid, overflow and sign extension. Your input never leaves your browser.

Width
Input is
Try:

How to use

  1. Choose the Width: 8, 16, 32 or 64 bits. Two's complement is always relative to a width; the same bits mean different numbers at different widths.
  2. Choose how the input is written. Decimal accepts a signed number such as -5. Hex pattern and Binary pattern take the bits as typed: a shorter pattern is padded with zeros on the left (zero extension, never sign extension).
  3. Read the summary: the bits, the hex form, the unsigned value and the signed value of the same bits, and whether the input fits as signed, as unsigned, as both, or as neither (overflow).
  4. The bit grid shows each bit with its weight. The top bit has a negative weight, -2^(width-1); that is the whole idea of two's complement. Click a bit to flip it and watch the values change.
  5. Below the grid, Negating this pattern shows invert, add 1 and any carry; Changing width shows sign extension, zero extension and truncation at every width; and the add check shows signed overflow and unsigned carry for adding 1.

Ranges the tool uses:

BitsSigned minimumSigned maximumUnsigned maximum
8-128127255
16-327683276765535
32-214748364821474836474294967295
64-9223372036854775808922337203685477580718446744073709551615

The minimum is -2n-1, the maximum is 2n-1 - 1, and the unsigned maximum is 2n - 1. The table is generated from the same code the tool uses, and the tests check each row.

Worked examples

Each value below is recomputed by an automated test from the tool's engine; the binary arithmetic is also written out and checked separately.

A negative number: -5 in 8 bits

The top bit has weight -128. 11111011 = -128 + 64 + 32 + 16 + 8 + 0 + 2 + 1 = -128 + 123 = -5. As unsigned, the same bits are 128 + 123 = 251 = 256 - 5.

Width 8, input is decimal

Input: -5

Output: 11111011 (hex FB); unsigned 251; signed -5; status signed-only

The textbook route is "invert and add one":

Width 8

Input: -5

Output: 00000101 -> invert 11111010 -> add 1 11111011

The same bits, read from a pattern

All ones, FF, is 255 unsigned and -1 signed: -128 + 127 = -1.

Width 8, input is hex pattern

Input: FF

Output: 11111111 (hex FF); unsigned 255; signed -1

At 32 bits the pattern 80000000 is a 1 followed by 31 zeros: the most negative 32-bit integer.

Width 32, input is hex pattern

Input: 80000000

Output: 10000000000000000000000000000000 (hex 80000000); unsigned 2147483648; signed -2147483648

The one number that negates to itself

Invert 10000000 and you get 01111111; add 1 and the carry runs all the way up and gives 10000000 again. There is no +128 in 8 bits.

Width 8

Input: 10000000

Output: 10000000 -> invert 01111111 -> add 1 10000000 (same pattern)

Widening and narrowing

Widening 11111011 (-5) to 16 bits: sign extension copies the top bit, zero extension adds zeros.

Width 8, input is binary pattern

Input: 11111011

Output: sign-extended 1111111111111011; zero-extended 0000000011111011

Narrowing keeps the low bits. 300 in 16 bits is 0000000100101100; cut to 8 bits it is 00101100, which is 44 (the top 1 is lost):

Width 16, pattern 012C

Input: 0000000100101100 (300 in 16 bits)

Output: sign-extended 00101100; zero-extended 00101100

Addition: signed overflow versus carry

127 + 1 in 8 bits: 01111111 + 00000001 = 10000000. No carry leaves the top bit, but the sign flipped from positive to negative, so signed overflow happened (the mathematically correct 128 does not fit).

Add patterns, width 8

Input: 127 and 1

Output: pattern 10000000; signed -128; unsigned 128; signed overflow yes; unsigned carry no

255 + 1 in 8 bits: 11111111 + 00000001 = 1 00000000. A carry leaves the top bit, so the unsigned result does not fit; but read as signed this is -1 + 1 = 0, which is correct, so there is no signed overflow.

Add patterns, width 8

Input: 255 and 1

Output: pattern 00000000; signed 0; unsigned 0; signed overflow no; unsigned carry yes

What goes wrong

Inputs that go wrong in real programs, with the tool's exact output.

300 does not fit in 8 bits

300 needs nine bits (100101100). Most code silently keeps the low eight. The tool flags it and shows exactly which bit was dropped.

Width 8, input is decimal

Input: 300

Output: 00101100 (hex 2C); unsigned 44; signed 44; dropped bit 1, status overflow

-129 does not fit in 8 bits

-129 is below -128, the smallest 8-bit value. Its 9-bit two's complement form is 101111111; keeping 8 bits turns it into +127, a change of sign.

Width 8, input is decimal

Input: -129

Output: 01111111 (hex 7F); unsigned 127; signed 127; dropped bit 1, status overflow

128 fits as unsigned but not as signed

128 is a valid uint8 but is not a valid int8. The same bits read as signed are -128.

Width 8, input is decimal

Input: 128

Output: 10000000 (hex 80); unsigned 128; signed -128; status unsigned-only

A short binary pattern is zero-extended, not sign-extended

Typing 4 bits into an 8-bit field does not mean "negative if it starts with 1". The pattern 1010 is padded with zeros to 00001010, which is 10. If you meant the 4-bit value -6, the sign has to be extended to 11111010 first, which is what the sign-extension table does.

Width 8, input is binary pattern

Input: 1010

Output: 00001010 (hex 0A); unsigned 10; signed 10

A digit that is not a bit

Width 8, input is binary pattern

Input: 9

Error: Character "9" at position 1 is not a valid binary digit.

Why a hex number in JavaScript is not negative

0xFF is the Number 255 in JavaScript, not -1, because Numbers are not fixed-width integers. To get the 8-bit signed value, wrap it explicitly: BigInt.asIntN(8, 255n) is -1n (MDN: BigInt.asIntN). For 32 bits, 0xFFFFFFFF | 0 is -1.

Limits & gotchas

  • Widths. 8, 16, 32 and 64 bits only. Odd widths such as 12 bits (common in sensors) are not offered; you can read a 12-bit value by sign-extending it by hand using the widening table.
  • Input size. At most 400 characters. Numbers are exact arbitrary-size integers, so 64-bit values do not lose precision the way a JavaScript Number would above 253.
  • Two's complement only. Sign-magnitude and ones' complement are other systems for signed integers and are not shown. Floating-point numbers use a sign bit and are covered on the IEEE 754 page.
  • The language rules differ. The tool states what the hardware-style arithmetic gives. In C, signed overflow is undefined behaviour and a right shift of a negative value is implementation-defined (cppreference), so your compiler may not behave like the wrapped result shown here. The bitwise calculator has the JavaScript rules.
  • Browser. Tested in a current Chrome only.

FAQ

How do I write -5 in 8-bit two's complement?

Write 5 in binary with 8 bits (00000101), invert every bit (11111010), then add 1 (11111011). That is hex FB, and 251 if you read the same bits as unsigned. Check by adding: 00000101 + 11111011 = 100000000 (256), and with only 8 bits kept the result is 00000000, so 11111011 behaves as -5. The page shows these steps for any input.

Why can 8 bits hold -128 but only +127?

There are 256 patterns. Zero uses one, 127 patterns are positive and 128 are negative, because the top bit is the sign and two's complement has a single zero. The extra pattern is 10000000 = -128. It has no positive twin: inverting it gives 01111111 and adding 1 gives 10000000 again, so negating the most negative number returns the same number. Wikipedia: Two's complement gives the 4-bit case, -8 to +7. In C, negating INT_MIN is undefined behaviour (cppreference).

What is the difference between sign extension and zero extension?

Both widen a bit pattern. Sign extension copies the top bit into all the new high bits, which keeps the signed value (11111011 = -5 becomes 1111111111111011 = -5 in 16 bits). Zero extension fills with 0s, which keeps the unsigned value (11111011 = 251 becomes 0000000011111011 = 251). Using the wrong one is a classic bug when a signed byte is widened: -5 turns into 251.

Why does 300 become 44 in 8 bits?

Because 300 is 100101100 in binary, nine bits. An 8-bit field keeps the low 8 bits, 00101100 = 44, and the top bit, 1, is dropped. Equivalently 300 - 256 = 44. The tool does not hide this: it marks the input as an overflow, shows the dropped bit, and shows what the value wraps to. In C, unsigned arithmetic wraps this way; signed overflow is undefined behaviour (cppreference).

How do I tell signed overflow from a carry?

They are two different flags for the same addition. A carry out of the top bit means the unsigned result did not fit (255 + 1 in 8 bits gives 00000000 with a carry, though as signed numbers -1 + 1 = 0 is perfectly correct). Signed overflow means the signed result did not fit (127 + 1 gives 10000000, which reads as -128, with no carry out). The page shows both worked examples, and the tool reports both flags for any pattern you add.

Sources

  • Wikipedia: Two's complement Used for: The most significant bit is the sign; one zero and one extra negative number (a 4-bit range of -8 to +7); invert-and-add-one; sign extension repeats the most significant bit; the most negative number has no positive counterpart.
  • MDN Web Docs: BigInt.asIntN() Used for: BigInt values are always encoded as two's complement; asIntN wraps a value to a signed width.
  • cppreference.com: C arithmetic operators Used for: In C a shift count that is negative or not smaller than the promoted width of the left operand is undefined behaviour; signed right shift of a negative value is implementation-defined; unsigned arithmetic wraps modulo 2^n; signed overflow is undefined.
  • MDN Web Docs: BigInt Used for: BigInt holds integers of arbitrary size; mixing BigInt and Number in arithmetic throws a TypeError.
  • Wikipedia: Positional notation Used for: A number is written as digits multiplied by powers of the base, with the radix point separating the integer and fractional parts.

Every document above was opened and read on 2026-10-02. Documentation changes; if a page here disagrees with the current docs, trust the docs and tell us.

The tests check every width against BigInt.asIntN and BigInt.asUintN on random values and against hand-worked bit patterns.