computers/bits-and-bytes-why-a-byte-can-t-count-past-255.md

Bits and bytes: why a byte can't count past 255

Computers · 4 min read ·

A byte is eight on/off switches, and that tiny size explains a lot of odd bugs. In this article you flip the bits of one byte yourself and watch it turn into a number, a negative number, or a letter.

You will see why 255 + 1 wraps around to 0, why 127 + 1 can become -128, and how the same bits can mean different things depending on how a program reads them. The Python examples are short and every one has been run.

Eight bit tiles showing 00001101 with place values 128 down to 1, the 8, 4 and 1 tiles lit green

You have probably heard that computers "only understand 1s and 0s". That is true, but it leaves out the interesting part: how can a row of 1s and 0s be a number, a letter, or a photo? And why do some programs show a score of -128 after reaching 127? The answer is a small idea called binary, and once you can see it, a whole family of odd bugs stops being mysterious.

A bit is one switch

A bit is the smallest piece of information a computer keeps: a switch that is either off (0) or on (1). One switch can only say two things, so computers group them. A group of 8 bits is called a byte. Every file you have ever saved is a long list of bytes.

Place values, the same trick you already know

In everyday numbers, each place is worth ten times the one to its right: ones, tens, hundreds. The number 345 means 3 hundreds + 4 tens + 5 ones. Binary uses the same idea, but each place is worth two times the one to its right: 1, 2, 4, 8, 16, 32, 64, 128. To read a binary number, add up the values of the switches that are on.

So 00001101 has the 8, 4 and 1 switches on: 8 + 4 + 1 = 13. Try it yourself below. Tap the bits to flip them, then use the buttons to add 1 and watch what happens at the edges.

Why a byte stops at 255

With 8 switches there are 2 × 2 × ... (eight times) = 256 different patterns, which cover the numbers 0 to 255. That is all the room there is. When you add 1 to 11111111, the answer needs a ninth bit, and the byte has nowhere to put it. The extra bit is dropped and the rest reads 00000000. This is called overflow, and it behaves like a car's odometer rolling over from 999999 back to 000000.

Python hides this because its whole numbers grow as large as memory allows. You can see the wrap-around by keeping only the lowest 8 bits yourself with & 0xFF:

print(255 + 1)            # 256, Python just makes room
print((255 + 1) & 0xFF)   # 0, what an 8-bit byte would hold
print((200 + 100) & 0xFF) # 44, because 300 - 256 = 44
print(2**100)             # 1267650600228229401496703205376

Many other languages and hardware use fixed sizes instead: a 32-bit integer holds 0 to 4,294,967,295 if unsigned, and a 64-bit one holds up to 18,446,744,073,709,551,615. Large, but not infinite.

Negative numbers: same bits, different reading

A byte has no minus sign, so how does it store -1? The common answer is called two's complement. The rule: the leftmost bit is worth -128 instead of +128. Then 11111111 = -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = -1. Flip the leftmost bit in the widget and compare the two result cards: the bits are identical, only the reading differs. A signed byte covers -128 to 127, which is why adding 1 to 127 gives -128.

def as_signed(n):
    n &= 0xFF
    return n - 256 if n >= 128 else n

print(as_signed(127 + 1))     # -128
print(as_signed(0b11111111))  # -1
print(format(-1 & 0xFF, "08b"))  # 11111111

Letters are numbers with an agreement

A computer cannot store the shape of a letter in a switch, so people agreed on a table: this number means that letter. The classic table is ASCII, where 65 is "A", 66 is "B", and 97 is "a". Modern text uses a larger table called Unicode, which keeps those same first 128 entries.

print(ord("A"), format(ord("A"), "08b"))  # 65 01000001
print(chr(0b01100001))                    # a
print(bin(13))                            # 0b1101
print(int("00001101", 2))                 # 13

Notice that the bits never say what they are. 01000001 is the number 65, the letter "A", or a shade of grey in an image, depending on what the program was told to expect. Most beginner confusion about "data types" comes from this one fact.

So what for your own code?

You will meet these limits in real places: a game score that suddenly goes negative, a counter that restarts at zero, a file format that stores a value in one byte and silently cuts off bigger ones. When a number goes strange at exactly 127, 255, 32,767 or 65,535, suspect a fixed-size integer. Knowing that the limit is a power of two minus one is often enough to find the bug in minutes.

$ ls computers/

see all →
computers/fetch-decode-execute-the-three-beat-loop-every-cpu-repeats-billions-of.md Fetch, decode, execute: the three-beat loop every CPU repeats billions of times a second A processor looks clever, but at its core it repeats one small loop billions of times a second: fetch an instruction, decode what it asks… 5 min read · 26 Oct computers/the-call-stack-why-a-function-that-never-stops-crashes-your-program.md The call stack: why a function that never stops crashes your program Every time a function is called, the computer puts a small block of memory called a frame on top of a call stack, and removes it when the… 5 min read · 23 Oct computers/floating-point-why-0-1-0-2-is-not-exactly-0-3.md Floating point: why 0.1 + 0.2 is not exactly 0.3 Type `0.1 + 0.2` into JavaScript or Python and you get `0.30000000000000004`. It is not a bug, and it is not your mistake. Computers store… 5 min read · 19 Oct computers/race-conditions-why-two-people-adding-1-to-5-can-leave-you-with-6.md Race conditions: why two people adding 1 to 5 can leave you with 6 Two phones add one item to a shared list of 5, and the list ends up at 6 instead of 7. Nothing is broken, yet an update was lost. This is a… 6 min read · 16 Oct computers/time-slices-how-one-cpu-core-runs-many-programs-at-once.md Time slices: how one CPU core runs many programs at once Your computer runs far more programs than it has processor cores. How? The operating system's scheduler gives each program a short time… 5 min read · 10 Oct computers/cpu-cache-why-reading-a-grid-by-rows-beats-columns-step-by-step.md CPU cache: why reading a grid by rows beats columns, step by step Two loops add up the same grid of numbers, yet one can run about ten times slower. The reason is a small, fast memory inside your processor… 5 min read · 7 Oct