Parity and Checksums

Every time data moves — down a cable, across a wireless link, off a scratched disc — there is a chance a bit gets flipped: a 0 arrives as a 1, or the other way round. A stray burst of electrical noise, a weak signal, a speck of dust: any of these can corrupt a single bit. The receiver has no way of seeing that anything went wrong — the bits it gets look just as valid as the bits that were sent.

So how does a computer notice? The trick is to send a little extra information alongside the data — a small, cheap fingerprint of it. If the data and its fingerprint no longer match at the far end, something got scrambled on the way. This is error detection, and the two classic tools A-level asks about are the parity bit and the checksum.

The parity bit: make the 1s add up

A parity bit is one extra bit tacked onto a group of data bits (often a byte of seven data bits plus one parity bit). Its only job is to make the count of 1s come out to an agreed shape:

The sender and receiver agree beforehand which scheme they use. The sender counts the 1s in the data and sets the parity bit accordingly. The receiver counts the 1s in everything it received: if the parity is now wrong (odd when it should be even, say), a bit must have flipped in transit.

Worked example — even parity

Suppose we want to send the seven data bits 1010110 using even parity. First count the 1s:

1,\,0,\,1,\,0,\,1,\,1,\,0 \;\Rightarrow\; \text{four ones}

Four is already even, so we don't need another 1 to even things up. The parity bit is 0, and we transmit the eight bits 1010110\,\mathbf{0}.

Now send 1101001 with even parity. Counting the 1s (1,1,0,1,0,0,1) gives four… no — read them off one more time: 1,1,0,1,0,0,1 is a one, a one, a one and a one — that's four ones. Even already, so the parity bit is again 0. Compare with 1101011, which has five ones: five is odd, so to reach an even count we set the parity bit to 1 and send 1101011\,\mathbf{1} (now six ones — even).

Try it — set a parity bit and catch a flip

This program counts the 1s in some data, works out the even-parity bit, then flips a bit and shows the receiver noticing. Change the data string or the flipAt position and press Run.

const data: string = "1010110"; // seven data bits — edit me const flipAt: number = 3; // which bit to corrupt (0 = first), or -1 for none // Count the 1s and choose the even-parity bit. const countOnes = (bits: string): number => [...bits].filter((b) => b === "1").length; const parity: string = countOnes(data) % 2 === 0 ? "0" : "1"; const sent: string = data + parity; // data bits followed by the parity bit console.log("Sending: " + sent + " (" + countOnes(sent) + " ones — even, good)"); // Corrupt one bit in transit. let received: string = sent; if (flipAt >= 0 && flipAt < sent.length) { const flipped = sent[flipAt] === "1" ? "0" : "1"; received = sent.slice(0, flipAt) + flipped + sent.slice(flipAt + 1); } console.log("Received: " + received + " (" + countOnes(received) + " ones)"); // The receiver checks: even parity means the total must be even. if (countOnes(received) % 2 === 0) { console.log("Parity OK — no error detected."); } else { console.log("PARITY ERROR — a bit was corrupted in transit!"); }

Checksums: a fingerprint for a whole block

A single parity bit protects a handful of bits. To guard a bigger block — a network packet, a downloaded file — we use a checksum: a value computed from all the data and sent alongside it. The receiver runs the same calculation on the data it received and checks that it gets the same checksum. A mismatch means the data changed on the way.

The simplest checksum just adds up the bytes. Say we send three bytes with values 60, 45 and 90. Their sum is 195; we send that as the checksum. If a byte arrives as 61 instead of 60, the receiver's sum comes to 196 \neq 195 — caught. Real checksums keep the value to a fixed size (for example, "sum the bytes modulo 256" so the result always fits in one byte), and stronger ones (like CRCs and cryptographic hashes) catch far more kinds of corruption than a plain sum.

// A tiny "sum modulo 256" checksum over a block of byte values. const block: number[] = [60, 45, 90, 200, 17]; const checksum = (bytes: number[]): number => bytes.reduce((total, b) => total + b, 0) % 256; const sentSum: number = checksum(block); console.log("Sender checksum: " + sentSum); // Corrupt one byte in transit (200 -> 201). const received: number[] = [60, 45, 90, 201, 17]; const recvSum: number = checksum(received); console.log("Receiver checksum: " + recvSum); console.log(sentSum === recvSum ? "Checksums match — data looks intact." : "Checksums DIFFER — the block was corrupted!");

When you download a big file, the site often lists a value like e3b0c44298fc1c14… next to it — a hash such as SHA-256. It's a checksum on steroids: a fixed-length fingerprint where changing even one bit of the file produces a wildly different value. Re-computing it on your copy and comparing lets you confirm the file arrived intact — and that nobody swapped it for a tampered version. Same core idea as our "sum the bytes", just enormously harder to fool.

Parity vs checksum — same idea, different scale

Both work by sending redundant information — a summary the receiver can re-derive. A parity bit is a one-bit summary of a few bits; a checksum is a many-bit summary of a whole block. The bigger and cleverer the summary, the more kinds of corruption it can spot — but the more overhead it adds. That trade-off is the whole game of error detection.

A single parity bit can be fooled. It only flips its verdict when the number of corrupted bits is odd. If two bits flip, the count of 1s changes by an even amount, so the parity comes out correct again and the error slips through unnoticed. In general, a single parity bit detects an odd number of bit errors and misses an even number.

And even when an error is detected, that is error detection, not error correction. Parity and simple checksums tell you that something went wrong; they don't tell you which bit, so they can't fix it — the usual response is to ask for the data to be sent again. Correcting errors (working out the original bits) needs more redundancy, as in Hamming codes.