What is −5 in 8-bit two's complement?
11111011 11111011, which is 0xFB.
Type a signed integer and get sign-magnitude, ones' complement, two's complement and offset binary at once, at 4 to 64 bits. Or paste a bit pattern or hex byte and see all five readings side by side. Local, free, no sign-up.
Type a signed whole number. All four representations are computed at once — you do not have to know in advance which one your system uses.
| Encoding | Bits | Hex |
|---|---|---|
| Sign-magnitude | 1000 0101 | 85 |
| Ones' complement | 1111 1010 | FA |
| Two's complement | 1111 1011 | FB |
| Offset binary | 0111 1011 | 7B |
Sign-magnitude and ones' complement each spend one bit pattern on negative zero, so they hold one fewer value than two's complement and cannot reach the most negative number.
You found a byte in a memory dump or a register and do not know how it is meant to be read. Paste it and see what it means under each interpretation at once — which one is right depends on the system that produced it, so all of them are shown.
| Read as | Value |
|---|---|
| Unsigned | 251 |
| Sign-magnitude | -123 |
| Ones' complement | -4 |
| Two's complement | -5 |
| Offset binary | 123 |
Computed by the same engine the tool above uses, so these values cannot drift from it.
| Decimal | Sign-magnitude | Ones' complement | Two's complement | Offset binary | Hex |
|---|---|---|---|---|---|
| 127 | 0111 1111 | 0111 1111 | 0111 1111 | 1111 1111 | 7F |
| 100 | 0110 0100 | 0110 0100 | 0110 0100 | 1110 0100 | 64 |
| 10 | 0000 1010 | 0000 1010 | 0000 1010 | 1000 1010 | 0A |
| 5 | 0000 0101 | 0000 0101 | 0000 0101 | 1000 0101 | 05 |
| 1 | 0000 0001 | 0000 0001 | 0000 0001 | 1000 0001 | 01 |
| 0 | 0000 0000 | 0000 0000 | 0000 0000 | 1000 0000 | 00 |
| -1 | 1000 0001 | 1111 1110 | 1111 1111 | 0111 1111 | FF |
| -5 | 1000 0101 | 1111 1010 | 1111 1011 | 0111 1011 | FB |
| -10 | 1000 1010 | 1111 0101 | 1111 0110 | 0111 0110 | F6 |
| -100 | 1110 0100 | 1001 1011 | 1001 1100 | 0001 1100 | 9C |
| -127 | 1111 1111 | 1000 0000 | 1000 0001 | 0000 0001 | 81 |
| -128 | — | — | 1000 0000 | 0000 0000 | 80 |
| Width | Two's complement / offset binary | Sign-magnitude / ones' complement |
|---|---|---|
| 4 | -8 … 7 | -7 … 7 |
| 8 | -128 … 127 | -127 … 127 |
| 16 | -32768 … 32767 | -32767 … 32767 |
| 32 | -2147483648 … 2147483647 | -2147483647 … 2147483647 |
| 64 | -9223372036854775808 … 9223372036854775807 | -9223372036854775807 … 9223372036854775807 |
Built and verified by the Go Tools engineering team.
11111011 11111011, which is 0xFB.
-128 … 127 −128 to 127 in two's complement; −127 to 127 in sign-magnitude and ones' complement.
value − 2^n If the top bit is 0 read it as unsigned; if it is 1, subtract 2^n from the unsigned reading.
−1 or 255 −1 as a signed byte, 255 as an unsigned one. The bits alone do not decide it.
Two's complement answers a hardware question, not a mathematical one: how do you store negative numbers so that the adder you already built keeps working? The trick is to represent −x by the pattern for 2^n − x. Addition then wraps around modulo 2^n and lands on the right answer with no special case for signs, which is why subtraction needs no separate circuit.
Two consequences follow and both show up in real bugs. First, the range is asymmetric: eight bits cover −128 to 127, not −128 to 128, because the patterns have to be shared out and there is no negative zero to make things even. Second, the sign is not a flag you can strip — the top bit of 11111011 is 1, but the value is −5 rather than −123, so reading a negative number means interpreting the whole word, not just looking at one bit.
Sign-magnitude and ones' complement are the two designs that lost. They are still worth knowing because IEEE 754 floating point kept the sign-magnitude layout, and because the comparison is what makes two's complement look inevitable rather than arbitrary.
// -5 as an 8-bit byte, three ways to arrive at the same pattern 0b00000101 // 5 ~0b00000101 // 11111010 ones' complement of 5 ~0b00000101 + 1 // 11111011 two's complement = -5 // In JavaScript the width matters: bitwise operators are 32-bit, // so anything wider has to go through BigInt. BigInt.asIntN(8, 0xFBn) // -5n BigInt.asUintN(8, -5n) // 251n BigInt.asIntN(64, 0xFFFFFFFFFFFFFFFBn) // -5n // C23 made two's complement mandatory for signed integers. // Before that, the other two encodings were legal but unused.
Sign-magnitude, ones' complement, two's complement and offset binary are computed together. Offset binary is the one most calculators leave out, and it is the one ADC datasheets keep using.
Paste the bits or the hex you actually have and see all five readings, unsigned included. This is the direction you need when a dump disagrees with the number the device reports.
Every value is handled with BigInt, so 0xFFFFFFFFFFFFFF9C resolves to −100 rather than to whatever a 32-bit truncation would produce.
At width 8, −128 has no sign-magnitude and no ones' complement form. The table says so instead of printing a pattern that does not mean that number.
Enter 0 and the second bit pattern for zero in sign-magnitude and ones' complement is shown, which is the clearest single argument for why two's complement won.
The 8-bit comparison table and the per-width ranges are rendered when the page is built, by the same engine that powers the live fields, so they cannot drift out of sync with it.
BigInt.asIntN, Python's int.from_bytes(..., signed=True) and C's fixed-width types give the authoritative answer for the code you are writing. Use them in the code; use this page when you have a value in front of you and no interpreter open.
Shows the value with the type the program declared, which is exactly the piece of information a bit pattern lacks. It cannot help when the bytes arrived over a wire with no declared type — that is the case this page is for.
Converts between bases, but only for non-negative values — negatives are explicitly rejected there because a base has no opinion about how a sign is stored. Signed representation is this page's job; use the base converter for magnitudes.
The floating-point counterpart. It keeps a sign-magnitude layout rather than two's complement, and biases the exponent by 2^(e−1)−1, so the two pages answer different questions about the same word of memory.
-5, width 8
sign-magnitude 1000 0101 ones' complement 1111 1010 two's complement 1111 1011 (0xFB) offset binary 0111 1011
The three encodings agree on the sign bit and disagree on everything else. Only the two's complement row is what a C int8_t actually holds.
0xFB, width 8
unsigned 251 sign-magnitude -123 ones' complement -4 two's complement -5 offset binary 123
-128, width 8
sign-magnitude no representation ones' complement no representation two's complement 1000 0000 (0x80) offset binary 0000 0000
Sign-magnitude and ones' complement each spend a bit pattern on negative zero, so they run from −127 to 127 and cannot reach −128. Tools that print a byte here are wrong.
0xFFFFFFFFFFFFFF9C, width 64
two's complement -100 unsigned 18446744073709551516
Anything wider than 32 bits has to be done with BigInt. JavaScript's |, << and >>> truncate to 32 bits silently, which is why some online calculators return the wrong answer here instead of an error.
4, 8, 16, 32 or 64. This is not a display preference — the same bits mean different numbers at different widths, so getting it wrong changes the answer.
Type a whole number, negative sign included. All four encodings update as you type, together with the hexadecimal form of each.
Paste a binary string or a 0x value into the reverse field to see what that exact pattern means under each interpretation, including the unsigned reading.
The page flags the two cases that trip people up: the most negative value having no sign-magnitude or ones' complement form, and zero having a second bit pattern in those two encodings.
Inverting the bits gives the ones' complement. Stopping there is off by one from the two's complement, and the error is easy to miss because the result still looks like a plausible negative number.
5 = 00000101 ~5 = 11111010 <- ones' complement, not -5
5 = 00000101 ~5 = 11111010 ~5 + 1 = 11111011 <- -5 in two's complement
JavaScript truncates the operands of bitwise operators to 32 bits. The high half disappears with no error, so the result is wrong rather than absent.
0xFFFFFFFFFFFFFFFB // 18446744073709552000 -- the literal is already rounded ~0xFFFFFFFFFFFFFFFB + 1 // 0 -- silently wrong, expected -5
BigInt.asIntN(64, 0xFFFFFFFFFFFFFFFBn) // -5n
Widening by padding with zeros keeps the number only when it is positive. For a negative value the sign bit has to be replicated across the new bits.
int8 0xFB (-5) int16 0x00FB (251) <- zero-extended
int8 0xFB (-5) int16 0xFFFB (-5) <- sign-extended
−128 has no sign-magnitude and no ones' complement representation in eight bits, because both encodings spend one pattern on negative zero. Printing 10000000 for it confuses the two's complement answer with an encoding that cannot express the number.
-128 sign-magnitude: 10000000 <- that pattern means -0
-128 sign-magnitude: no representation at width 8 -128 two's complement: 10000000
0xFF9C. Unsigned that is 65436, which is not a temperature. At width 16 the two's complement row shows −100, and with a 0.1 °C scale factor the sensor is telling you −10.0 °C.n−1 bits are the magnitude, read as a plain unsigned number. Range is −(2^(n−1)−1) to 2^(n−1)−1, symmetric, with two zeros. It is the layout IEEE 754 uses for floating point.2^n − 1 − x. Same range and same two zeros as sign-magnitude. Addition needs an end-around carry, which is exactly the complication two's complement removes. The apostrophe placement is not a typo: ones' complement is relative to a word of all ones, while two's complement is relative to a single power of two.−x is stored as 2^n − x. Range is −2^(n−1) to 2^(n−1)−1, deliberately asymmetric, with one zero. Addition, subtraction and multiplication of the low word are all sign-agnostic, which is the whole reason it won.value + 2^(n−1), so −2^(n−1) becomes all zeros and the patterns sort in the same order as the values they encode. It equals the two's complement pattern with the top bit flipped. Beware the naming: IEEE 754 exponent fields are biased by 2^(e−1)−1, one less than the offset used here.&, |, ~ and the shifts to 32-bit integers before operating and converts back afterwards, so a 64-bit value loses its high half without any error being raised. Every conversion on this page is done on arbitrary-precision integers instead, which is also why the 64-bit extremes come out exact.−(−128) is still −128 for a signed byte. Any code that computes an absolute value needs a plan for this input, and any test suite should contain it.0xFB into a 16-bit field as 0x00FB turns −5 into 251. Widening a signed value means replicating the sign bit, giving 0xFFFB.BigInt.asIntN in JavaScript, int.from_bytes(..., signed=True) in Python and fixed-width types in C say what they mean and handle the edges. Hand-rolled ~x + 1 is where the width bugs come from.2^n − x, which makes subtraction and addition the same circuit and gives the number line exactly one zero. 00000101 → 11111010 → 11111011. The flip step alone gives you the ones' complement, which is why the two are always one apart. n bits it covers −2^(n−1) to 2^(n−1)−1, because it does not waste a pattern on negative zero the way sign-magnitude and ones' complement do. That extra slot lands on the negative side. int8_t or uint8_t. value + 2^(n−1), so the smallest value is all zeros and ordering the raw patterns as unsigned integers also orders the signed values. It shows up in ADC and DAC outputs and in audio sample formats. Note that IEEE 754 exponents use a different bias — 2^(e−1)−1, not 2^(e−1) — so do not carry the number across. 65436 while the device meant the two's complement value −100. Paste 65436 as hex 0xFF9C at width 16 here and the two's complement row shows the intended reading. ~x + 1 silently loses the top half of a 64-bit value and reports a plausible but wrong result. This tool uses BigInt throughout, which is why the 64-bit rows here agree with what your debugger shows. 00000000 and 10000000 both mean zero; in ones' complement it is 00000000 and 11111111. Two comparisons that should be equal can therefore compare unequal bit by bit. Two's complement has a single zero, which removed a whole class of hardware special cases. Conversion Tools
Convert between binary, hex, decimal, octal and any base (2-36) instantly. Free, private — all processing in your browser.
Conversion Tools
Convert Linux file permissions between octal (755, 644) and rwx symbols. Get chmod commands, spot risky settings like 777 — free, right in your browser.
Conversion Tools
Convert HEX to RGB, HSL, OKLCH, OKLAB and CMYK in your browser — copy any format with one click. Free, no signup, your colors never leave the page.
Conversion Tools
Convert HEX colors to CMYK in your browser. Naive sRGB-based approximation for print previews. Free, no signup, your colors stay local.
Conversion Tools
Convert any hex color to HSL in your browser — 3-digit, 6-digit, 8-digit alpha all supported. Free, instant, no signup, your colors never leave the page.
Conversion Tools
Convert HEX to OKLCH for Tailwind v4 design tokens. Live perceptually-uniform output with Display P3 gamut warnings. Free, browser-only.