Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

1Learning Outcomes

2Introduction

Historically, computers were used as scientific calculators. We therefore dedicate most of our time to understanding how a string of bits (a bit string) can represent a number.

How can we use NN bits to represent a set of integers?

There are many systems we can use. Not all systems will help us represent 2N2^N unique integers in NN bits! We will focus on representing signed and unsigned integers.

3NN-bit Unsigned Integer Representation

Let’s get our standard unsigned integer representation out of the way first. The mathematical scheme discussed earlier is sufficient for representing 2N2^N unsigned integers with NN bits.

This representation is supported in C (discussed more later). Built-in types like unsigned int can introduce ambiguity because it doesn’t specify the width of an int. The header inttypes.h accommodates typedefs like uint8_t, uint16_t, uint32_t, etc. to specify unsigned integer representations that are 8-bit, 16-bit, 32-bit etc.

4Design Considerations

We will prefer certain systems over others, depending on what sorts of integer operations we want to support.

4.1Common number operations

In decimal, we like to add, subtract, multiply, divide, and compare numbers. So we must be able to do the same thing with bit representations of numbers.

It turns out that many arithmetic operations translate reasonably well between decimal and binary.

For example, let’s add 10 and 7, which are 1010 and 0111, respectively, in binary. The result is the number 17, or 10001 in binary.

 11 carry bits 1010+ 011110001\begin{array}{rrl} & \texttt{ 11 }\hspace*{0.5em} & \text{carry bits} \\ & \texttt{ 1010} \\ + & \texttt{ 0111} \\ \hline & \texttt{10001} & \end{array}

Subtraction in binary works similarly. We leave an in-depth discussion of implementing binary comparison (e.g., X<YX < Y) to a future project.

4.2The Odometer Analogy

In theory, numbers have an infinite number of digits (usually leading zeros), but in computing, we must allocate a finite number of bits. Hardware is limited! Binary bit patterns are therefore abstractions: they are simply representatives of numbers.

In choosing an integer representation, we must consider whether the operations supported will still work within the given bit width of an integer representation. One useful analogy for considering edge cases comes from the idea of an odometer:

"Close-up photograph of a mechanical car odometer showing the reading 999999 just before it rolls over. The image illustrates a finite counting device that will wrap back to 000000 after one more tick."

Figure 1:A car odometer measures mileage. It starts at 0 and slowly ticks up, then wraps around again. At some point, the odometer above will hit 999999; the next number is again 0.

Two sets of values to consider:

As we will see, there are systems in which the “directions” of these values may diverge.

4.3Integer Overflow

Integer overflow: The arithmetic result is outside the representable range of integers.

Suppose we use NN bits to represent integers in hardware. If the result of an integer operation (+,,×,÷,<,=,+, -, \times, \div, <, =, \leq, etc.) cannot be accurately represented in NN bits, we say that integer overflow occurred.

"A blue horizontal line marked with 4-bit binary values from 0000 to 1111 illustrates a finite number system. An gold curved line connects the maximum value back to the minimum value to visually represent the concept of arithmetic overflow in digital systems."

Figure 2:With unsigned integers, the “binary odometer” wraps around.

4-bit unsigned integers: Using 4 bits, you can represent 0 through 15.

4.4NN-bit Signed Integer Representations

How do you represent negative numbers? More generally, how do you represent both positive and negative numbers (and zero) with the same NN bits?

Sidebar: There was a king who asked his wise thinkers to teach him economics. They kept bringing him long books, and he kept sending them away to make it shorter. Finally, they came back and said, "Sire, we have the theory of economics in four words: ‘Ain’t No Free Lunch.’ " It means you can’t get something for nothing.

If we want to represent negative numbers, you’ve got to give something up; you lose some of the positive numbers you used to have. If we borrow a bit, we can’t go as high in the positive range, but now we can do negatives.

Next, we discuss a few reasonable ones and consider tradeoffs. In the next section, we’ll reveal the standard representation used in modern architectures and supported by the C23 standard.

5Sign-Magnitude

  • Leftmost sign bit: the integer’s sign. 0 is positive; 1 is negative.

  • Rest of bits: magnitude of the integer in binary

4-bit Sign-Magnitude

  • Positive numbers: 1 (0b0001) to 7 (0b0111)

  • Negative numbers: -1 (0b1001) to -7 (0b1111)

  • Two zeros: +0 (0b0000) and -0 (0b1000)

We already see one problem! With a positive and a negative zero, we’d have to check for two different patterns in code, every time we want to compare values to zero.

"Two equations display the hexadecimal values 0x00000000 and 0x80000000 equating to positive and negative zero, respectively. Curved lines map the hexadecimal digits to a binary expansion, illustrating that the leading bit determines the sign while the remaining bits represent the magnitude of zero."

Figure 3:Sign-Magnitude has two representations for zero: “positive zero” and “negative zero.”

Let’s examine a subtler problem, revealed via the binary odometer:

"A blue horizontal number line displays 4-bit binary values to illustrate sign-magnitude representation, with 0000 at the center. Two gold arrows point in opposite directions from the center to indicate how values increase in magnitude for both positive and negative binary sequences."

Figure 4:“Binary odometer” for 4-bit sign-magnitude.

The problem with Sign and Magnitude is that as the odometer goes up, it goes the wrong way: you go positive, positive, and then suddenly you hit the negative range. Incrementing the binary odometer 0000 to 1111 starts at 0, then 1, through to 7, then wraps to 0 again, then -1, then -7. In other words, sometimes integer addition corresponds to adding bits, and sometimes integer addition corresponds to subtracting bits. This would get complicated very quickly!

Ultimately, Sign-Magnitude is considered a straw man[1] approach for supporting general purpose computing with integers. Nevertheless, it has some reasonable applications in, say, signals processing, where users are more commonly looking to decouple sign from magnitude, much less add numbers together. Ask us for more.

6Ones’ Complement

To represent a negative number, complement the bits of its positive representation.

Here, “complement” means that if the bit is 0 change it to 1, and vice versa. Equivalently, to change the sign of a number, flip all bits of its binary representation.

-7 with 8-bit Ones’ Complement

"A blue horizontal number line displays 4-bit binary values to illustrate ones' complement representation, centered around the values 0000 and 1111. Two gold arrows point to the right to indicate that both positive and negative binary sequences increase in value as the odometer increments from left to right."

Figure 5:“Binary odometer” for 4-bit ones’ complement.

Another added benefit of Ones’ Complement

The leftmost bit (also known as most significant bit) is still effectively the sign bit.

...But we still have the problem of two zeros! Historically, one’s complement was used for a while, but eventually abandoned for two’s complement.

7Two’s Complement

Ones’ complement:

"A blue horizontal number line displays 4-bit binary values and their corresponding decimal equivalents from -8 to 7 to illustrate two's complement representation. Two gold arrows point to the right across the entire scale, indicating that adding to the binary value consistently increases the numerical value across both negative and positive ranges."

Figure 6:“Binary odometer” for 4-bit twos’ complement.

Of note:

In Two’s Complement, a bit pattern of all ones is -1.

7.1Arithmetic and conversion

Hardware for two’s complement is now simple.

Addition is exactly the same as with an unsigned number.

The numbers 5 and -5 are represented in 4-bit two’s complement with 0b0101 and 0b1011, respectively. Adding them together should result in 0, or 0b0000.

"A diagram compares the decimal addition of positive and negative five with the equivalent operation in two's complement binary, adding 0101 and 1011. The binary calculation displays red carry bits and results in a five-bit sum where the leading bit is discarded to achieve the correct four-bit value of 0000, which is the number zero."

Figure 7:Addition in two’s complement follows the decimal intuition.

7.2Formal definition

We can write the value of an nn-digit two’s complement number as

2n1dn1+i=0n22idi- 2^{n-1} d_{n-1} + \sum_{i=0}^{n-2} 2^i d_i

Positive and negative numbers can be computed using the same formula. Above, the sign is computed by multiplying the highest bit by (2n1)(-2^{n-1}).

Example: 5 and -5 in 4-bit two’s complement

0b1011=(1×23)+(0×22)+(1×21)+(1×20)=8+0+2+1=5\begin{align} \texttt{0b1011} &= (1 \times -2^3) + (0 \times 2^2) + (1 \times 2^1) + (1 \times 2^0) \\ &= -8 + 0 + 2 + 1 \\ &= -5 \\ \end{align}
0b0101=(0×23)+(1×22)+(0×21)+(1×20)=0+4+0+1=5\begin{align} \texttt{0b0101} &= (0 \times -2^3) + (1 \times 2^2) + (0 \times 2^1) + (1 \times 2^0) \\ &= 0 + 4 + 0 + 1 \\ &= 5 \\ \end{align}

7.3Two’s Complement: Flip sign

Hardware to convert positive to negative (& vice versa) is simple.

  1. Complement all bits

  2. Then add 1

"Two procedures illustrate the two's complement sign-change process by converting positive five to negative five and vice versa. Each example demonstrates flipping the bits of the starting binary value and then adding one to obtain the final result with the opposite sign."

Figure 8:Two’s Complement: To change sign, flip the bits and add one.

At home: Prove algorithm is equivalent to formula!

The intuition comes from a “number wheel” representation of our binary odometer (Figure Figure 9). This wheel also helps us identify where integer overflow occurs:

"A horizontal number line and a circular number wheel visually represent the continuity and overflow points of 4-bit two's complement integers. Yellow warning triangles mark the critical boundary between the maximum positive value 0111 and the minimum negative value 1000 to indicate where arithmetic overflow occurs."

Figure 9:Top: A number line indicating where integer overflow occurs. Bottom: A number “wheel” indicating the same integer overflow location.

In Figure 9, 0 through 7 stays the same as it has for every representation. But then it jumps to -8. That cool top-level term (-8) pulls all negative numbers down by one so there is no overlap at zero.

7.4Two’s Complement: C standard (as of 2025)

Two’s complement is the C23 standard number representation for signed integers. Again, the built-in int is ambiguous because it does not specify bitwidth. And again, the header stdint.h accommodates typedefs like int8_t, int16_t, int32_t, etc., for signed integer representations.

8Bias Encoding

Bias Encoding:

  • Keep track of a bias.

  • To interpret stored binary: Read the data as an unsigned integer, then subtract the bias

  • To store an integer as data: Add the bias, then store the resulting number as an unsigned integer.

Imagine you are recording an electrical signal wavering between 0 and 31 volts. Wouldn’t it be cool to grab that graph and pull it down so it wiggles around zero? That’s bias encoding.

We can shift to any arbitrary bias we want to suit our needs. To represent (nearly) as many negative numbers as positive, a commonly-used bias for NN-bits is (2N11)(2^{N-1} - 1).

"A diagram presents two parallel horizontal number lines. Vertical lines connect specific points on the top line to corresponding values on the bottom line to indicate the mapping between the two systems."

Figure 10:A bias-encoded representation effectively shifts the number line to an unsigned representation.

Example: N=4N = 4 with bias (2N11)(2^{N-1} - 1)

  • 4-bit integer representation

  • Bias: (2411)=7(2^{4-1} - 1) = 7

Here are some diagrams in case they are useful. Figure 11 represents a bias encoding where N=4N = 4 and bias =7 = 7. The odometer just does the right thing; it counts up through zero with nothing strange happening.

"A blue horizontal number line displays 4-bit binary values and their corresponding decimal equivalents from -7 (for 0000) to 8 (for 1111) to illustrate bias encoding. A single gold arrow points to the right to indicate that the decimal values increase monotonically as the binary sequence increments from 0000 to 1111."

Figure 11:“Binary odometer” for 4-bit bias-encoded integers, with bias 7.

You may also find the number wheel useful for seeing where overflow happens, and how integers increase with respect to binary incrementing. See Figure 12.

"A circular number wheel visually represents a 4-bit bias-encoded integer. Values inside and outside the wheel represent the numbers and bit representations, respectively; the wheel has tickmarks going from -7 (0000) to 1 (1000) to 8 (1111)."

Figure 12:Number wheel for bias encoding.

We really like biased encoding for some specific applications we’ll see later in the course.

Footnotes
  1. Wikipedia: Straw Man