# Binary-coded decimal (BCD)

*Storing decimal digits one nibble each*

Binary-coded decimal (BCD) stores each decimal digit in its own 4-bit group using the 8421 weights, so the digits 0 to 9 map to 0000 to 1001 and the six patterns 1010 to 1111 are unused.

Group: Number & logic
URL: https://digiwleea.wleeaf.dev/learn/bcd/

[Binary](https://digiwleea.wleeaf.dev/learn/binary/) packs a whole number into one continuous string of bits, so decimal `59` becomes `0011 1011`. That is dense and efficient, but it scrambles the decimal digits together: there is no `5` and no `9` to be found in `0011 1011`. **Binary-coded decimal** (BCD) takes the opposite approach. It keeps each decimal digit in its **own** group of four bits, coded just like a small binary number, so the digits stay visible and separate.

> **TIP:** Think of an old mechanical odometer or a price display: a row of little wheels, each showing one decimal digit `0` through `9`. BCD is the digital version of that row. Every digit gets its own four-bit wheel, and you read the number digit by digit exactly as printed, rather than converting the whole thing out of one big binary value.

## One nibble per digit (the 8421 code)

Each decimal digit is stored in one [nibble](https://digiwleea.wleeaf.dev/learn/binary/) (4 bits) using the ordinary place values `8, 4, 2, 1`, which is why plain BCD is also called **8421 code**. The digit `0` is `0000`, the digit `9` is `1001`, and you read a nibble by adding the weights of its `1` bits, just like binary. The catch is that a nibble can hold sixteen patterns but a decimal digit only needs ten:

| decimal digit | BCD (8421) |
| --- | --- |
| 0 | 0000 |
| 1 | 0001 |
| 2 | 0010 |
| 3 | 0011 |
| 4 | 0100 |
| 5 | 0101 |
| 6 | 0110 |
| 7 | 0111 |
| 8 | 1000 |
| 9 | 1001 |

_The ten BCD digit codes. Each is just the 4-bit binary value of the digit. The six remaining patterns 1010 (10) through 1111 (15) are not valid BCD: a correct BCD nibble never holds them._

So decimal `59` in BCD is `0101 1001`: the nibble `0101` is the `5` and `1001` is the `9`. Compare that with pure binary, where `59` is `0011 1011`, a single value with no separable digits. The same number, two very different bit patterns.

## The six wasted codes, and packed versus unpacked

Because only ten of every sixteen patterns are used, BCD throws away `1010` through `1111`, six codes per nibble. That is its main cost: a byte in pure binary holds `0` to `255`, but the same byte as two BCD digits holds only `0` to `99`, wasting about a third of its capacity. How those digits are packed into bytes has two styles:

- **Packed BCD**: two digits per byte, one in each nibble. The byte `0101 1001` is the two digits `59`. This is the compact form, and the one used for BCD arithmetic.
- **Unpacked BCD**: one digit per byte, in the low nibble, with the high nibble left `0000` (or used for a sign or a character code). The digit `9` becomes the byte `0000 1001`. This wastes more space but is easy to convert to printable text.

## Why BCD exists, and what it costs

> **KEY:** BCD is chosen whenever staying *exactly* decimal matters. **Money** is the big one: a value like `0.10` dollars has no exact representation in binary fractions (it repeats forever, like `1/3` in decimal), so binary arithmetic can drift by tiny rounding errors, whereas BCD stores cents exactly. **Displays** are the other: a [decoder](https://digiwleea.wleeaf.dev/learn/decoder/) can turn each BCD nibble straight into the segments of one digit, with no division to extract digits. The price you pay is the six wasted codes per nibble and, as the next section shows, arithmetic that needs a correction step.

## BCD addition and the +6 correction

Adding BCD digits starts with an ordinary binary [adder](https://digiwleea.wleeaf.dev/learn/fulladder/), but a plain binary sum can land on one of the six invalid codes or carry wrongly, because the adder counts in sixteens while a decimal digit rolls over at ten. The fix is a simple rule: after the binary add, if the nibble result is greater than `9` **or** it produced a carry out of the nibble, **add `6` (`0110`)** to skip past the six unused codes. That correction both fixes the digit and generates the proper decimal carry into the next digit.

1. Add the two BCD digits (and any incoming carry) with a normal 4-bit binary adder.
2. If the result is `9` or less and there was no carry out, it is already valid BCD: done.
3. If the result is greater than `9` or a carry came out of the nibble, add `0110` (6). The low nibble of that sum is the corrected digit, and a `1` carries into the next decimal digit.

Worked example, `5 + 8 = 13`. As binary, `0101 + 1000 = 1101`, which is `13`, greater than `9`, so the result is invalid BCD and we add `6`:

```
0101 + 1000 = 1101 (13 > 9)   ->   1101 + 0110 = 1 0011   ->   carry 1, digit 0011   =>   BCD 0001 0011 = "13"
```

The `+6` pushed the result past the six wasted codes, leaving the units digit `0011` (3) and carrying a `1` into the tens digit, so the answer reads `0001 0011`, which is BCD for `13`. Every BCD adder is a binary adder plus this conditional `+6` corrector on each digit.

## Designing the correction detector on a K-map

The whole `+6` rule hinges on one test: is the 4-bit binary sum greater than `9`? That test is itself a small logic function of the sum bits, and a [Karnaugh map](https://digiwleea.wleeaf.dev/learn/karnaugh/) hands you the gates in two strokes. Label the adder's four sum bits `S3 S2 S1 S0` (weights `8, 4, 2, 1`). The detector output, call it `GT9`, is `1` for the six invalid codes `1010` through `1111` and `0` for the ten valid digits `0000` through `1001`:

| S3 | S2 | S1 | S0 | GT9 |
| --- | --- | --- | --- | --- |
| 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 1 | 0 |
| 0 | 0 | 1 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 | 0 |
| 1 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 0 | 1 | 1 | 1 |
| 1 | 1 | 0 | 0 | 1 |
| 1 | 1 | 0 | 1 | 1 |
| 1 | 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 |

_The greater-than-9 detector for a BCD adder's sum nibble. GT9 is 1 only for the six invalid codes 1010 (10) through 1111 (15); the valid digits 0000 through 1001 (including 1000 = 8 and 1001 = 9) all give 0._

Drop those `1`s onto a four-variable K-map with `S3 S2` choosing the row and `S1 S0` choosing the column, both Gray-ordered `00, 01, 11, 10`. The six `1`s fall into two large rectangular blocks of four:

1. The whole `S3=1, S2=1` row (`1100, 1101, 1110, 1111`) is a block of four. Its two changing bits `S1` and `S0` cancel, leaving the term `S3·S2`.
2. The `2 x 2` block where `S3=1` and `S1=1` (`1010, 1011, 1110, 1111`) is another block of four. Its changing bits `S2` and `S0` cancel, leaving `S3·S1`.
3. OR the two blocks. Every invalid code is covered and no valid digit is: `GT9 = S3·S2 + S3·S1`.

```
GT9 = S3·S2 + S3·S1 = S3·(S2 + S1)      (1 for 1010..1111, 0 for 0000..1001)
```

So the correction fires when `GT9` is true **or** the adder already carried out of the nibble. That one signal, `C = Cout + S3·S2 + S3·S1`, does double duty: it switches the `+6` corrector on, and it is the decimal carry into the next digit's adder. Two AND gates and two OR gates turn a plain 4-bit [adder](https://digiwleea.wleeaf.dev/learn/fulladder/) into one decimal digit's worth of BCD adder.

## Binary to BCD, and driving a display

The very same six-code correction is how you turn a pure [binary](https://digiwleea.wleeaf.dev/learn/binary/) value into BCD digits, by the **shift-and-add-3** method (also called *double dabble*). You shift the binary number left one bit at a time into a set of 4-bit BCD digit columns, and before each shift you add `3` to any column that is already `5` or more. Adding `3` to a digit and then doubling it (the shift) is exactly adding `6` after the doubling, since `2 * (d + 3) = 2d + 6`, and a digit only doubles past `9` when it was `5` or more (`2d >= 10` means `d >= 5`). So it is the identical `>9 -> +6` rule, applied one step earlier. Once you have clean BCD digits, each one drives a [seven-segment decoder](https://digiwleea.wleeaf.dev/learn/seven-segment/), itself just a handful of K-map-minimized segment functions, to light the display.

> **TIP:** Worked shift-and-add-3: convert binary `11111` (decimal 31) with two BCD columns, tens and units. Shifting the bits in one at a time, the units column reaches `0111` (7) after three shifts. Since `7 >= 5`, add `3` before the next shift, then continue; two corrections later the columns settle on tens `0011` (3) and units `0001` (1), so the BCD result is `0011 0001` = decimal `31`. The corrections are what keep each column a legal `0` to `9` digit instead of running into the six invalid codes.

## Excess-3: a self-complementing alternative

**Excess-3** codes each digit as its value **plus 3**, so `0` is `0011` and `9` is `1100`. The payoff is that it is **self-complementing**: the 9's complement of a digit (what you need for decimal subtraction) is just the bitwise [NOT](https://digiwleea.wleeaf.dev/learn/not/) of its code. Inverting `0011` (the code for 0) gives `1100`, which is the code for 9, and `0` and `9` are 9's complements. That makes subtraction circuitry simpler, the reason Excess-3 was used in some early machines.

| digit | 8421 BCD | Excess-3 |
| --- | --- | --- |
| 0 | 0000 | 0011 |
| 1 | 0001 | 0100 |
| 4 | 0100 | 0111 |
| 5 | 0101 | 1000 |
| 8 | 1000 | 1011 |
| 9 | 1001 | 1100 |

_A few digits in 8421 BCD and in Excess-3 (value + 3). Excess-3 is self-complementing: invert every bit of a code and you get the code for the 9's complement digit. 0 (0011) inverts to 1100 (9); 4 (0111) inverts to 1000 (5)._

The single decimal digit below is a BCD nibble you can set by hand. Its four bits carry the weights `8, 4, 2, 1`, and only the patterns `0000` through `1001` are legal BCD values.

_Circuit diagram: One BCD digit: set the four bits d3-d0 (weights 8, 4, 2, 1) and read the decimal digit they spell, 0 to 9. Open it in the lab and try to make 9 (1001); anything above that, like 1010, is an invalid BCD code. A BCD-to-7-segment decoder would turn each such nibble into the lit segments of a display digit._

> **WARN:** **Common mistakes.** BCD is **not** pure binary: the byte `0101 1001` is `59` read as BCD but `89` read as a plain binary number, so never mix the two readings. Three more traps: the codes `1010` through `1111` are **invalid** in BCD and a correct digit nibble never holds one; BCD addition needs the conditional `+6` correction whenever a digit exceeds `9` or carries, since a bare binary add gives a wrong BCD result; and remember BCD wastes six of every sixteen codes, so it is less dense than binary (a byte holds `0`-`99`, not `0`-`255`).

**Q (Try it):** Add the BCD digits `7` and `6`. Show the binary sum, decide whether the `+6` correction is needed, and give the two-digit BCD result.

**A:** `7 + 6 = 13`. As binary, `0111 + 0110 = 1101`, which is `13`, greater than `9`, so the `+6` correction is needed: `1101 + 0110 = 1 0011`. That is a carry of `1` and a units nibble of `0011` (3), so the result is `0001 0011`, which is BCD for `13`.

> **KEY:** BCD is the trade you make when exact decimal beats raw density: it keeps money and on-screen digits precise and easy to display, and in return you accept wasted codes and a correction step in the [adder](https://digiwleea.wleeaf.dev/learn/fulladder/). It is also a first taste of choosing an encoding to fit a job rather than to be compact, the same kind of choice behind [Gray code](https://digiwleea.wleeaf.dev/learn/gray-code/). Next, codes that add bits on purpose to *catch* mistakes: [error detection and correction](https://digiwleea.wleeaf.dev/learn/error-codes/).

### FAQ

**Q:** What is binary-coded decimal (BCD)?

**A:** BCD stores each decimal digit in its own group of four bits using the place values `8, 4, 2, 1`, so `0` to `9` map to `0000` to `1001`. A multi-digit number keeps its digits separate, for example decimal `59` is `0101 1001`, rather than being packed into one binary value.

**Q:** Why use BCD instead of binary?

**A:** Because it stays exactly decimal. Money values like `0.10` have no exact binary-fraction representation and can drift with rounding, while BCD stores the digits precisely. BCD also feeds displays easily, since each nibble can be turned straight into one digit's segments by a decoder, with no need to divide a binary value into digits.

**Q:** What are the invalid BCD codes?

**A:** The six patterns `1010`, `1011`, `1100`, `1101`, `1110`, and `1111` (decimal 10 to 15). A valid BCD nibble only ever holds `0000` through `1001`, so those six codes are unused, which is why BCD wastes about a third of a byte's capacity (a byte holds `0`-`99` instead of `0`-`255`).

**Q:** Why do you add 6 in BCD addition?

**A:** A binary adder counts in sixteens, but a decimal digit must roll over at ten. When a digit's binary sum exceeds `9` or carries out of the nibble, adding `6` (`0110`) skips the six unused codes, leaving the correct decimal digit and producing the proper carry into the next digit. For example `5 + 8` gives binary `1101`, and `1101 + 0110` corrects it to `0001 0011`, BCD for `13`.

**Q:** What is the difference between packed and unpacked BCD?

**A:** Packed BCD stores two digits per byte, one in each nibble (the byte `0101 1001` is `59`), and is the compact form used for arithmetic. Unpacked BCD stores one digit per byte in the low nibble, leaving the high nibble `0000` or using it for a sign, which wastes more space but is easy to turn into printable text.

**Q:** How do you build a BCD adder's +6 correction logic?

**A:** Detect when the 4-bit binary sum exceeds `9`. On a [Karnaugh map](https://digiwleea.wleeaf.dev/learn/karnaugh/) of the sum bits `S3 S2 S1 S0`, the six invalid codes `1010` through `1111` group into `S3·S2 + S3·S1`. OR that with the adder's carry-out to get one signal that both switches on the `+6` corrector and carries into the next decimal digit.

**Q:** How do you convert a binary number to BCD?

**A:** Use shift-and-add-3, also called double dabble: shift the binary value left one bit at a time into 4-bit BCD digit columns, and before each shift add `3` to any column that is already `5` or more. Adding `3` before doubling equals adding `6` after (`2 * (d + 3) = 2d + 6`), so it is the same greater-than-9 correction applied one step earlier. When every bit has been shifted in, the columns hold the decimal digits.
