Signed Numbers & Negative Values

How Computers Represent Negative Numbers in Binary

Introduction: The Problem of Negative Numbers

Computers work with binary—sequences of 0s and 1s. This works perfectly for counting: 0, 1, 10, 11, 100... But what about negative numbers? There's no "minus sign" in binary. How does a computer know the difference between 5 and -5?

This seemingly simple question has a surprisingly deep answer. Over the decades, computer scientists developed three major approaches to representing negative numbers in binary. Each has tradeoffs, and understanding them reveals fundamental insights about how computers really work.

The Core Challenge

Binary only has two symbols: 0 and 1. We need to encode the concept of "negative" using only these two symbols. Whatever method we choose must work efficiently with computer hardware—ideally using the same circuits for both positive and negative numbers.

In this comprehensive guide, we'll explore all three methods:

  • Sign-Magnitude: The intuitive approach (like how we write -5)
  • One's Complement: An improvement with a clever trick
  • Two's Complement: The modern standard used in virtually all computers

By the end, you'll understand not just how these systems work, but why two's complement became the universal choice, and how to perform arithmetic with signed binary numbers confidently.

Unsigned vs. Signed: The Fundamental Choice

Before we can represent negative numbers, we need to understand the distinction between unsigned and signed integers.

Unsigned Integers

Unsigned integers can only represent zero and positive numbers. All n bits contribute to the magnitude:

Bits Minimum Value Maximum Value Total Values
8 bits 0 255 256
16 bits 0 65,535 65,536
32 bits 0 4,294,967,295 ~4.3 billion
64 bits 0 18,446,744,073,709,551,615 ~18 quintillion

Signed Integers

Signed integers can represent negative, zero, and positive numbers. This requires "spending" some of the bit patterns on negative values:

Bits Minimum Value Maximum Value Total Values
8 bits (signed) -128 +127 256
16 bits (signed) -32,768 +32,767 65,536
32 bits (signed) -2,147,483,648 +2,147,483,647 ~4.3 billion
64 bits (signed) -9,223,372,036,854,775,808 +9,223,372,036,854,775,807 ~18 quintillion

The Tradeoff

Signed and unsigned integers of the same bit width can represent the same number of values, but different ranges. An unsigned 8-bit integer goes 0 to 255; a signed 8-bit integer goes -128 to +127. You trade away half your positive range to gain negative numbers.

When to Use Each

  • Unsigned: Memory sizes, array indices, bit flags, color values, ages, counts of things
  • Signed: Temperatures, coordinates, differences, financial values, positions relative to origin

Sign-Magnitude Representation

The most intuitive approach to representing negative numbers mirrors how humans write them: use one bit as a "sign" and the rest as the magnitude.

How It Works

In sign-magnitude representation:

  • The leftmost bit (most significant bit) indicates the sign: 0 = positive, 1 = negative
  • The remaining bits represent the absolute value (magnitude)

4-Bit Sign-Magnitude Examples

    0 1 0 1  →  + 5   (sign bit 0 = positive, magnitude 101 = 5)
    1 1 0 1  →  - 5   (sign bit 1 = negative, magnitude 101 = 5)

    0 1 1 1  →  + 7   (maximum positive)
    1 1 1 1  →  - 7   (minimum negative)

    0 0 0 0  →  + 0   (positive zero)
    1 0 0 0  →  - 0   (negative zero!)
                        

Complete 4-Bit Sign-Magnitude Table

Binary Decimal Binary Decimal
0000+01000-0
0001+11001-1
0010+21010-2
0011+31011-3
0100+41100-4
0101+51101-5
0110+61110-6
0111+71111-7

The Problems with Sign-Magnitude

1. Two Representations of Zero

Both 0000 (+0) and 1000 (-0) represent zero. This wastes one bit pattern and complicates comparisons—is -0 equal to +0? The answer should be yes, but the bits are different.

2. Complex Addition Circuitry

Adding two numbers requires checking signs first. If signs match, add magnitudes. If signs differ, subtract the smaller from the larger and use the sign of the larger. This requires separate subtraction hardware.

3. Comparison Complexity

You can't simply compare bits to determine which number is larger. 1001 (-1) looks "bigger" than 0001 (+1) as a bit pattern, but it's actually smaller as a number.

Arithmetic Complications

Example: 5 + (-3) in Sign-Magnitude

    5 = 0101 (positive)
   -3 = 1011 (negative)

    Step 1: Signs differ, so we need to subtract magnitudes
    Step 2: |5| > |3|, so result is positive
    Step 3: 5 - 3 = 2
    Step 4: Apply positive sign: 0010

    Result: +2 = 0010 ✓
                        

Notice how much logic is required! We can't just add the numbers directly. The hardware must check signs, compare magnitudes, select the operation, and determine the result's sign.

Where Sign-Magnitude is Still Used

Despite its flaws for integers, sign-magnitude is used in floating-point numbers (IEEE 754). The exponent and mantissa have separate meanings, so the simplicity of sign-magnitude makes sense there.

One's Complement

One's complement improves on sign-magnitude by using a simple rule: to negate a number, flip all its bits. This creates a more symmetric representation and simplifies some operations.

How It Works

To find the one's complement (negative) of a binary number:

  1. Take the original binary number
  2. Flip every bit: 0 becomes 1, 1 becomes 0

One's Complement Examples

    +5 = 0101
         ↓ flip all bits
    -5 = 1010

    +7 = 0111
         ↓ flip all bits
    -7 = 1000

    +1 = 0001
         ↓ flip all bits
    -1 = 1110
                        

Complete 4-Bit One's Complement Table

Binary Decimal Binary Decimal
0000+01111-0
0001+11110-1
0010+21101-2
0011+31100-3
0100+41011-4
0101+51010-5
0110+61001-6
0111+71000-7

Notice that positive numbers start with 0, negative numbers start with 1—the most significant bit still indicates the sign, but the relationship to magnitude is different from sign-magnitude.

Arithmetic with One's Complement

One's complement allows us to use the same addition hardware for both addition and subtraction! To subtract, we add the one's complement of the number.

Example: 5 - 3 using One's Complement

    5 - 3 = 5 + (-3)

    5 = 0101
   -3 = 1100 (one's complement of 0011)

        0 1 0 1   (+5)
      + 1 1 0 0   (-3)
      ---------
      1 0 0 0 1   (5 bits!)
          ↑
       Carry out

    The carry out must be added back (end-around carry):
        0 0 0 1   (4-bit result without carry)
      +       1   (carry)
      ---------
        0 0 1 0   = +2 ✓
                        

The End-Around Carry Problem

The "end-around carry" is one's complement's peculiarity: when addition produces a carry out, that carry must be added back to the result. This requires an extra addition step.

Example: (-2) + (-3) in One's Complement

    -2 = 1101 (one's complement of 0010)
    -3 = 1100 (one's complement of 0011)

        1 1 0 1   (-2)
      + 1 1 0 0   (-3)
      ---------
      1 1 0 0 1   (5 bits, carry out)

    End-around carry:
        1 0 0 1   (4-bit result)
      +       1   (carry)
      ---------
        1 0 1 0   = -5 ✓

    Verify: 1010 flipped = 0101 = 5, so 1010 = -5 ✓
                        

Remaining Problem: Two Zeros

One's complement still has two representations of zero: 0000 (+0) and 1111 (-0). This complicates comparisons and wastes one bit pattern.

Historical Use

One's complement was used in some early computers, including the UNIVAC 1101 (1950) and the CDC 6600 (1964). The Internet Protocol checksum still uses one's complement arithmetic because it has useful properties for error detection.

Two's Complement: The Modern Standard

Two's complement is the representation used in virtually all modern computers. It solves both problems of previous methods: there's only one zero, and arithmetic works without special cases.

How It Works

To find the two's complement (negative) of a binary number:

  1. Take the one's complement (flip all bits)
  2. Add 1 to the result

Alternatively, starting from the right: copy all bits up to and including the first 1, then flip the remaining bits.

Two's Complement Conversion Examples

    Finding -5 from +5:

    +5 = 0101
         ↓ flip all bits (one's complement)
         1010
         ↓ add 1
    -5 = 1011 ✓

    Finding -3 from +3:

    +3 = 0011
         ↓ flip all bits
         1100
         ↓ add 1
    -3 = 1101 ✓

    Finding -1 from +1:

    +1 = 0001
         ↓ flip all bits
         1110
         ↓ add 1
    -1 = 1111 ✓
                        

Shortcut Method: Copy and Flip

    Finding -6 from +6:

    +6 = 0110
         ↓ From right: copy until first 1, then flip

         0 1 1 0  (original)
               ↑  copy this 0
             ↑    copy this 1 (first 1 found)
           ↑      flip this 1 → 0
         ↑        flip this 0 → 1

    -6 = 1010 ✓

    Verify: 1010 → flip = 0101, add 1 = 0110 = 6 ✓
                        

Complete 4-Bit Two's Complement Table

Binary Unsigned Signed (2's comp)
000000
00011+1
00102+2
00113+3
01004+4
01015+5
01106+6
01117+7
10008-8
10019-7
101010-6
101111-5
110012-4
110113-3
111014-2
111115-1

Key Observations

  • Only one zero: 0000 is the only representation of zero
  • Asymmetric range: -8 to +7 (one more negative than positive)
  • Sign bit: MSB is still 0 for positive, 1 for negative
  • -1 is all 1s: 1111 = -1 (this is useful!)

Why Two's Complement Works

Two's complement isn't arbitrary—it's mathematically elegant. Consider 4-bit arithmetic as a circle with 16 positions:

Imagine the numbers 0-15 arranged in a circle. When you add 1 to 15, you wrap around to 0. Two's complement simply relabels half the circle as negative:

    Unsigned:   0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15  [wrap to 0]
    Signed:     0 +1 +2 +3 +4 +5 +6 +7 -8 -7 -6 -5 -4 -3 -2 -1  [wrap to 0]
                        

Adding 1 to -1 (1111) gives 10000. Discarding the overflow bit gives 0000 = 0. It just works!

The mathematical basis is modular arithmetic. In n-bit arithmetic, all operations are performed modulo 2ⁿ. A negative number -x is represented as 2ⁿ - x, which is exactly what two's complement computes.

Why -3 = 1101 in 4-bit Two's Complement

    In 4-bit arithmetic, everything is mod 16.

    -3 is represented as 16 - 3 = 13 = 1101₂

    Adding +5 and -3:
        5 + 13 = 18
        18 mod 16 = 2 ✓

    In binary:
        0101 + 1101 = 10010
        Discard overflow bit: 0010 = 2 ✓
                        

Converting To and From Two's Complement

Reading a Negative Number

To find the decimal value of a negative two's complement number:

What is 1011 in two's complement?

    Method 1: Convert back to positive
    1011 → flip bits → 0100 → add 1 → 0101 = 5
    Therefore, 1011 = -5

    Method 2: Use the formula
    For n bits: value = -2^(n-1) × MSB + remaining bits

    1011: -2³ × 1 + 2¹ × 1 + 2⁰ × 1
        = -8 + 2 + 1
        = -5 ✓

    Method 3: Subtract from 2ⁿ
    1011₂ = 11₁₀ (as unsigned)
    16 - 11 = 5
    Therefore it represents -5 ✓
                        

Range of Two's Complement Numbers

For an n-bit two's complement number:

  • Minimum value: -2^(n-1)
  • Maximum value: 2^(n-1) - 1
Bits Range Most Negative Most Positive
4 -8 to +7 1000 0111
8 -128 to +127 10000000 01111111
16 -32768 to +32767 1000...0 0111...1
32 -2.1B to +2.1B 1000...0 0111...1

The Asymmetry Explained

There's one more negative number than positive because zero is considered "positive" (its bit pattern starts with 0). With 4 bits we have: one zero, seven positives (1-7), and eight negatives (-8 to -1).

Signed Arithmetic in Detail

The magic of two's complement is that addition and subtraction work exactly the same as with unsigned numbers. The hardware doesn't need to know whether numbers are signed or unsigned!

Addition with Signed Numbers

Example 1: (+5) + (+3) = +8 (positive + positive)

    Using 5-bit two's complement:

        0 0 1 0 1   (+5)
      + 0 0 0 1 1   (+3)
      -----------
        0 1 0 0 0   (+8) ✓
                        

Example 2: (+5) + (-3) = +2 (positive + negative)

    Using 5-bit two's complement:
    -3 = flip(00011) + 1 = 11100 + 1 = 11101

        0 0 1 0 1   (+5)
      + 1 1 1 0 1   (-3)
      -----------
      1 0 0 0 1 0
          ↑
       Discard overflow carry (normal in 2's complement)

        0 0 0 1 0   (+2) ✓
                        

Example 3: (-5) + (-3) = -8 (negative + negative)

    Using 5-bit two's complement:
    -5 = 11011
    -3 = 11101

        1 1 0 1 1   (-5)
      + 1 1 1 0 1   (-3)
      -----------
      1 1 1 0 0 0
          ↑
       Discard overflow carry

        1 1 0 0 0   (= -8) ✓

    Verify: 11000 → flip = 00111, add 1 = 01000 = 8
    Therefore 11000 = -8 ✓
                        

Example 4: (-7) + (+3) = -4

    Using 5-bit two's complement:
    -7 = 11001
    +3 = 00011

        1 1 0 0 1   (-7)
      + 0 0 0 1 1   (+3)
      -----------
        1 1 1 0 0   (-4) ✓

    Verify: flip(11100) + 1 = 00011 + 1 = 00100 = 4 ✓
                        

Subtraction with Signed Numbers

Subtraction is simply addition of the two's complement:

A - B = A + (-B) = A + (two's complement of B)

Example: 7 - 4 = 3

    Using 4-bit two's complement:

    7 = 0111
    4 = 0100, so -4 = 1100

    7 - 4 = 7 + (-4):
        0 1 1 1   (7)
      + 1 1 0 0   (-4)
      ---------
      1 0 0 1 1
          ↑
       Discard carry

        0 0 1 1   = 3 ✓
                        

Example: 3 - 7 = -4

    Using 4-bit two's complement:

    3 = 0011
    7 = 0111, so -7 = 1001

    3 - 7 = 3 + (-7):
        0 0 1 1   (3)
      + 1 0 0 1   (-7)
      ---------
        1 1 0 0   = -4 ✓

    Verify: flip(1100) + 1 = 0011 + 1 = 0100 = 4 ✓
                        

Multiplication Considerations

Multiplication of signed numbers requires care. You can't simply multiply the bit patterns as if they were unsigned:

Example: (-3) × 2 = -6

    Using 4-bit values:
    -3 = 1101
     2 = 0010

    If we multiply as unsigned:
    1101 × 0010 = 11010 (26 in unsigned!)

    Correct method: Sign-extend and use larger result:
    -3 = 11111101 (8-bit)
     2 = 00000010 (8-bit)

    Or: Multiply magnitudes, determine sign separately:
    3 × 2 = 6
    Signs: (negative) × (positive) = negative
    Result: -6 = 1010 (4-bit) ✓
                        

Hardware Support

CPUs typically have separate multiply instructions for signed (IMUL) and unsigned (MUL) multiplication. The bit manipulation is different internally, even though the operands look the same.

Signed Overflow: The Silent Killer

Signed overflow is more subtle than unsigned overflow. It occurs when the result of an operation falls outside the representable range, causing the sign to change unexpectedly.

When Overflow Occurs

  • Adding two positives → negative: Overflow (result too large)
  • Adding two negatives → positive: Overflow (result too small)
  • Adding positive and negative: Never overflows!

Example: Positive Overflow in 4-bit

    5 + 6 should equal 11, but 4-bit signed max is 7:

        0 1 0 1   (+5)
      + 0 1 1 0   (+6)
      ---------
        1 0 1 1   = -5 in two's complement!

    Two positives gave a negative = OVERFLOW!
                        

Example: Negative Overflow in 4-bit

    (-5) + (-4) should equal -9, but 4-bit signed min is -8:

        1 0 1 1   (-5)
      + 1 1 0 0   (-4)
      ---------
      1 0 1 1 1
          ↑
       Discard carry
        0 1 1 1   = +7!

    Two negatives gave a positive = OVERFLOW!
                        

Detecting Signed Overflow

Overflow occurs when the carry into the sign bit differs from the carry out of the sign bit:

Carry In Carry Out Overflow?
00No
01Yes (positive overflow)
10Yes (negative overflow)
11No

CPUs set an "overflow flag" (OF or V) when this condition is detected, allowing programs to check for overflow after arithmetic operations.

Sign Extension

When you need to represent a number with more bits (e.g., converting 8-bit to 16-bit), you must preserve the sign. This is called sign extension.

How Sign Extension Works

Copy the sign bit (MSB) into all the new positions:

Positive Number Extension

    +5 in 4-bit:  0101
    +5 in 8-bit:  00000101   (fill with 0s)
    +5 in 16-bit: 0000000000000101

    The sign bit is 0, so we extend with 0s.
                        

Negative Number Extension

    -5 in 4-bit:  1011
    -5 in 8-bit:  11111011   (fill with 1s)
    -5 in 16-bit: 1111111111111011

    The sign bit is 1, so we extend with 1s.

    Verify: 11111011
    Flip:   00000100
    Add 1:  00000101 = 5
    Therefore 11111011 = -5 ✓
                        

Why Sign Extension Preserves Value

In two's complement, the sign bit has a negative weight: -2^(n-1). When you extend the number, you add more negative bits at the top, but they cancel out: -2^n + 2^(n-1) = -2^(n-1). The value remains unchanged!

Zero Extension vs. Sign Extension

  • Zero extension: For unsigned numbers, fill new bits with 0
  • Sign extension: For signed numbers, fill with the sign bit

Using the wrong extension type causes serious bugs:

Wrong Extension Example

    -5 in 4-bit (signed): 1011

    Zero-extended to 8-bit: 00001011 = +11 (WRONG!)
    Sign-extended to 8-bit: 11111011 = -5 (CORRECT)
                        

Comparing Representations

Let's summarize all three signed representations:

Property Sign-Magnitude One's Complement Two's Complement
Negation Flip sign bit Flip all bits Flip all + add 1
Zero representations Two (+0, -0) Two (+0, -0) One
Range (n bits) -(2^(n-1)-1) to +(2^(n-1)-1) -(2^(n-1)-1) to +(2^(n-1)-1) -2^(n-1) to +(2^(n-1)-1)
Addition hardware Complex (check signs) Simple + end-around carry Simple
Subtraction Needs subtractor Add complement Add complement
Used today? Floating-point sign IP checksums All integer arithmetic

Why Two's Complement Won

Two's complement requires the simplest hardware—the same adder works for both positive and negative numbers without modification. There's one unique zero. The range is maximally efficient. It's simply the best solution.

Real-World Applications

Programming Languages

Language Signed Types Unsigned Types
C/C++ char, short, int, long unsigned versions
Java byte, short, int, long None (except char)
Python 3 int (arbitrary precision) N/A
JavaScript Number (float64) N/A (bitwise ops use int32)
Rust i8, i16, i32, i64, i128 u8, u16, u32, u64, u128

Common Pitfalls

Mixing Signed and Unsigned

In C, comparing signed and unsigned values can give unexpected results. -1 > 0U is true because -1 is converted to unsigned (becoming a large positive number).

Integer Promotion

Small types are "promoted" to int for calculations. A signed char multiplied by another signed char produces a signed int, not a char.

Negating the Minimum

For 32-bit signed: -(-2147483648) = -2147483648! The minimum value has no positive equivalent, so negation overflows back to itself.

Assembly Language Perspective

At the assembly level, the same bits can be interpreted as signed or unsigned. The CPU provides different instructions:

  • JG/JL: Jump if greater/less (signed comparison)
  • JA/JB: Jump if above/below (unsigned comparison)
  • IMUL: Signed multiply
  • MUL: Unsigned multiply
  • SAR: Shift arithmetic right (preserves sign)
  • SHR: Shift logical right (fills with zeros)

Practice Problems with Solutions

Conversion Problems

Problem 1: What is -42 in 8-bit two's complement?

Show Solution
    42 = 00101010
    Flip: 11010101
    Add 1: 11010110

    -42 = 11010110 ✓
                            

Problem 2: What decimal value does 10110101 represent in 8-bit two's complement?

Show Solution
    10110101 (MSB is 1, so negative)
    Flip: 01001010
    Add 1: 01001011 = 75

    Therefore 10110101 = -75 ✓

    Alternative method:
    -128 + 32 + 16 + 4 + 1 = -128 + 53 = -75 ✓
                            

Arithmetic Problems

Problem 3: Calculate (-15) + (+23) in 8-bit two's complement

Show Solution
    -15 = 11110001
    +23 = 00010111

        1 1 1 1 0 0 0 1
      + 0 0 0 1 0 1 1 1
      -----------------
      1 0 0 0 0 1 0 0 0
          ↑
       Discard carry

        0 0 0 0 1 0 0 0 = 8 ✓
                            

Problem 4: Does 01111010 + 00010101 overflow in 8-bit signed?

Show Solution
    01111010 = +122
    00010101 = +21
    Sum should be 143, but max is 127...

        0 1 1 1 1 0 1 0
      + 0 0 0 1 0 1 0 1
      -----------------
        1 0 0 0 1 1 1 1 = -113 (wrong!)

    YES, overflow occurred.
    Two positives gave a negative = overflow.

    Carry into sign bit: 1
    Carry out of sign bit: 0
    Different carries = overflow detected.
                            

Problem 5: Sign extend 1010 from 4 bits to 8 bits

Show Solution
    1010 (4-bit signed = -6)
    Sign bit is 1, so extend with 1s:
    11111010 (8-bit signed = -6) ✓

    Verify: flip(11111010) = 00000101
    Add 1: 00000110 = 6
    Therefore 11111010 = -6 ✓
                            

Summary

Understanding signed number representation is essential for any serious programmer or computer scientist. Here's what you've learned:

  • Sign-magnitude is intuitive but has two zeros and complex arithmetic
  • One's complement improves arithmetic but still has two zeros
  • Two's complement is the universal standard: one zero, simple arithmetic
  • The same addition hardware works for both signed and unsigned numbers
  • Overflow detection checks the carry into/out of the sign bit
  • Sign extension preserves value when widening signed numbers

With this knowledge, you can reason about how any computer handles negative numbers—from microcontrollers to supercomputers.