Skip to main content
●GuideNovember 5, 20266 min read

Two's Complement Explained: How to Write Negative Numbers in Binary

Why 0xFF can mean 255 or -1: write negative numbers in binary with two's complement, read signed hex values, sign-extend, and catch overflow.

ShareXLinkedIn
Two's Complement Explained: How to Write Negative Numbers in Binary
Contents · 09 sections
  1. Why computers use two's complement
  2. The range for each width
  3. How to write a negative number in binary, step by step
  4. How to read a signed value in hex
  5. Sign extension: making a value wider without changing it
  6. Overflow: when the answer doesn't fit
  7. Two's complement in JavaScript and Python
  8. Checking values in the browser with BitLens
  9. Quick checklist

Short answer: to write a negative number in two's complement, pick a bit width, write the positive number in binary at that width, invert every bit, and add 1. In 8 bits, -5 becomes 0000 0101 → 1111 1010 → 1111 1011, or 0xFB. To read a pattern back, check the top bit: if it is 0 the value is positive; if it is 1, take the unsigned value and subtract 2ⁿ. So 0xFB is 251 − 256 = -5.

That is the whole method. The rest of this guide covers why it works, how to read signed values in hex dumps and logs, and the three mistakes that cause most real bugs: wrong width, wrong extension and silent overflow.

Why computers use two's complement

A fixed number of bits can only hold a fixed number of patterns. Eight bits give 256 patterns. If you read them as unsigned, they mean 0 to 255. If you read them as signed two's complement, the same 256 patterns mean -128 to 127.

The trick is that the top bit carries a negative weight. In 8 bits, the bit positions are worth -128, 64, 32, 16, 8, 4, 2 and 1. So 1111 1011 is -128 + 64 + 32 + 16 + 8 + 2 + 1 = -5. You can check any value this way, and it is a good way to build intuition.

This layout has one big advantage: addition and subtraction work the same way for signed and unsigned numbers. The processor adds the bits and keeps the low n bits; only the interpretation changes. There is one zero (0000 0000), not a "positive zero" and a "negative zero", which is why two's complement replaced older schemes such as sign-and-magnitude.

Every 4-bit pattern read as unsigned and as signed two's complement

The 4-bit table shows the pattern clearly. From 0000 to 0111 both readings agree. From 1000 onwards, the signed reading is the unsigned value minus 16, so 1111 is 15 unsigned and -1 signed.

The range for each width

For n bits, the signed range is -2ⁿ⁻¹ to 2ⁿ⁻¹ − 1:

Width Signed range Unsigned range
8-bit -128 to 127 0 to 255
16-bit -32,768 to 32,767 0 to 65,535
32-bit -2,147,483,648 to 2,147,483,647 0 to 4,294,967,295
64-bit -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 0 to 18,446,744,073,709,551,615

The range is not symmetric. There is one more negative value than positive, because zero takes one of the "non-negative" patterns.

How to write a negative number in binary, step by step

Take -100 in 8 bits.

  1. Choose the width. Two's complement only makes sense at a fixed width. Here it is 8 bits, so the valid range is -128 to 127 and -100 fits.
  2. Write the positive value, padded to the width. 100 = 64 + 32 + 4, so 0110 0100.
  3. Invert every bit. 1001 1011.
  4. Add 1. 1001 1100, which is 0x9C.
  5. Check it. 0x9C is 156 unsigned, and 156 − 256 = -100.

There is also a shortcut that skips the addition. Start from the right of the positive value, copy every bit up to and including the first 1, then invert everything to its left. For 0110 0100, copy 100 and invert 01100 to 10011. The result is 1001 1100 again.

A second shortcut works when you have a calculator: the n-bit pattern for a negative number -x is 2ⁿ − x. In 8 bits, -100 is 256 − 100 = 156 = 0x9C. In 32 bits, -100 is 4,294,967,296 − 100 = 4,294,967,196 = 0xFFFFFF9C.

How to read a signed value in hex

Hex dumps, packet captures and debugger output rarely tell you whether a field is signed. If you know the width, the rule is simple:

  • If the top hex digit is 0 to 7, the top bit is 0 and the signed value equals the unsigned value.
  • If the top hex digit is 8 to F, the top bit is 1. Subtract 2ⁿ from the unsigned value.

A few examples:

Pattern Width Unsigned Signed
0x7F 8-bit 127 127
0x80 8-bit 128 -128
0xFF 8-bit 255 -1
0xFF9C 16-bit 65,436 -100
0xFFFFFF9C 32-bit 4,294,967,196 -100
0x0000009C 32-bit 156 156

The last two rows show why width matters. 0x9C is -100 as an 8-bit signed value, but if a log prints it as a 32-bit value with leading zeros, it is 156. Never guess the width from the number of digits you can see, because leading zeros are often dropped.

Sign extension: making a value wider without changing it

When a signed 8-bit value is copied into a 16-bit or 32-bit variable, the new high bits must be copies of the old top bit. That is sign extension.

  • 0x9C (-100 in 8 bits) sign-extends to 0xFF9C in 16 bits and 0xFFFFFF9C in 32 bits. All three are -100.
  • 0x64 (+100 in 8 bits) extends to 0x0064 and 0x00000064.

If the high bits are filled with zeros instead (zero extension), 0x9C becomes 0x009C, which is +156. This is a classic bug when bytes are read from a file or a network buffer: the byte type is unsigned, the field is meant to be signed, and a temperature of -100 turns into 156.

Overflow: when the answer doesn't fit

Because the width is fixed, results that fall outside the range wrap around. In 8-bit signed arithmetic, 100 + 100 should be 200, but 200 is outside -128 to 127. The bits come out as 1100 1000, which reads as 200 − 256 = -56.

A quick test for signed overflow in addition: if two numbers with the same sign produce a result with the opposite sign, the result overflowed. Adding a positive and a negative number can never overflow.

Negating the most negative value is the other edge case. In 8 bits, -128 is 1000 0000. Invert it to 0111 1111, add 1, and you get 1000 0000 again. There is no +128 in 8 bits, so the negation of -128 is -128. The same happens with the minimum value at every width, and it is the reason abs() of the minimum integer can return a negative number in many languages.

Two's complement in JavaScript and Python

The idea is the same everywhere, but languages show it differently.

JavaScript numbers are floating-point, but the bitwise operators work on 32-bit signed integers:

  • ~5 is -6, because inverting the bits of x gives -x − 1.
  • -5 >>> 0 is 4294967291, the unsigned 32-bit reading of the same bits. Use (-5 >>> 0).toString(16) to get fffffffb.
  • -8 >> 1 is -4 (the sign bit is copied in), while -8 >>> 1 is 2147483644 (zeros are shifted in).

Python integers have no fixed width, so bin(-5) prints -0b101, with a minus sign rather than a bit pattern. To see the two's complement bits, mask to the width you want: -5 & 0xFF gives 251 (0xFB). To go the other way, subtract 2ⁿ when the top bit is set: x - 256 if x & 0x80 else x.

In other languages, check the specification for how signed shifts and out-of-range conversions behave rather than relying on what one compiler does.

Checking values in the browser with BitLens

When you are reading a hex dump in a web page, a log viewer or documentation, converting by hand is easy to get wrong. BitLens is our free Chrome extension for this kind of work. It converts between decimal, hex, binary and octal as you type, shows signed two's complement readings for 8-, 16-, 32- and 64-bit widths, runs bitwise operations masked to the chosen width, and includes an IEEE 754 float view and ASCII/Unicode lookup. You can also highlight a number on a web page, right-click, and send it to BitLens.

BitLens is available for Chrome. You can add BitLens to Chrome from the Chrome Web Store.

Quick checklist

  • Decide the width before anything else.
  • To negate: invert all bits, add 1. Or compute 2ⁿ − x.
  • To read: top bit 0 means positive; top bit 1 means subtract 2ⁿ.
  • Widen signed values with sign extension, not zero extension.
  • Watch for overflow when two same-sign numbers produce the opposite sign.
  • Remember that the minimum value has no positive counterpart.

For more conversions, the binary, hex and octal cheat sheet covers base conversion and bitwise masks, and how to read an IEEE 754 float covers how floating-point numbers use their bits.

Filed undertwos complementbinarysigned integershexadecimalbitwisebitlens

ShareXLinkedIn

● More from the journal

  1. 01

    Image Resizer 1.0.0: HEIC Support and a Pro Plan

    Image Resizer 1.0.0 opens HEIC and HEIF photos, keeps every preset and resize mode free, and adds a one-time €7.99 Pro for export packs and bigger batches.

    AnnouncementNovember 4, 2026
  2. 02

    How to Resize Images for Instagram, X, LinkedIn and YouTube in Chrome or Firefox

    One photo, six platforms. How to resize images for Instagram, X, LinkedIn, Facebook, YouTube and WhatsApp in Chrome or Firefox, without cutting off the subject.

    GuideNovember 4, 2026
  3. 03

    How to Convert HEIC to JPG in Chrome or Firefox (Without Uploading the Photo)

    Chrome and Firefox can't open iPhone HEIC photos. Here's how to turn them into JPG on your own device: iPhone settings, Mac Preview, or a browser extension.

    TutorialNovember 4, 2026