Basic

The limit of a fixed width

A fixed number of bits can only hold so many values. Past the top, the count wraps around to the bottom, and that wrap is a bug that no error message reports.

What you will see

4294967296

About 2 min of reading

Try It

Probe the wrap at a width.

1

Add one past the top of a byte.

print((255 + 1) % 256)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
0
2

Subtract one below zero.

print((0 - 1) % 256)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
255
3

Store three hundred in a byte.

print((200 + 100) % 256)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
44
The value wrapped, so it reads far smaller than it was.
4

Print what thirty two bits hold.

print(2 ** 32)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
4294967296

Data Flow

A fixed width holds a fixed count of values, and one past the top wraps to the bottom with no error.
1 width fixes the count
↓
2 past the top wraps
↓
3 the wrap is silent
↓
4 wider rows cost more bytes
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

print((255 + 1) % 256) 0
Why this works
The wrap is a silent bug

Overflow does not raise in most languages. The program keeps running with a wrong number, which is why it reaches production so often.

Widths are a contract

A format states its width, and a value that does not fit is a contract violation. Catching it at the edge is the fix, not reading a wrong number.

Examples

Wrap at the top

print((255 + 1) % 256)

One past the top of a byte is zero. The row of bits has nowhere to carry, so it starts over.

Wrap at the bottom

print((0 - 1) % 256)

One below zero is the top. The row rolls the other way, which is the same rule in reverse.

A counter that wraps

n = 255
n = (n + 1) % 256
print(n)

A byte-sized counter goes back to zero. A score that resets at 256 is this exact bug.

Bigger widths are calmer

print(2 ** 32)

Thirty two bits hold four billion values. The wrap is still there, it is just far away and easy to forget.

The wrap is silent

print((200 + 100) % 256)

Three hundred stored in a byte is forty four. Nothing crashed, the number is simply wrong.

Detect the wrap

a, b = 200, 100
print(a + b > 255)

Checking the result against the width is how a wrap is caught. The check has to be written on purpose.

Widths are chosen

print(2 ** 8, 2 ** 16, 2 ** 32)

Widths are picked to fit the biggest expected value with room left over. Too small and it wraps.

The cost of a width

print(2 ** 64)

A wider row holds more values and takes more bytes. Choosing a width is trading memory against the risk of a wrap.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Negative numbers in bits
Previous Lesson
Negative numbers in bits
Next Lesson
How a decimal is stored
How a decimal is stored →