Though BCD is not as widely used as it once was, decimal fixed-point and floating-point are still important and still used in financial, commercial, and industrial computing; modern decimal floating-point representations use base-10 exponents, but not BCD encodings.
In BCD, a digit is usually represented by four bits which, in general, represent the values/digits/characters 0-9. Other bit combinations are sometimes used for sign or other indications.
To BCD-encode a decimal number using the common encoding, each decimal digit is stored in a four-bit nibble.
Decimal: 0 1 2 3 4 5 6 7 8 9
BCD: 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001
Thus, the BCD encoding for the number 127 would be:
0001 0010 0111
Since most computers store data in eight-bit bytes, there are two common ways of storing four-bit BCD digits in those bytes:
Unlike binary-encoded numbers, BCD-encoded numbers can easily be displayed by mapping each of the nibbles to a different character. Converting a binary-encoded number to decimal for display is much harder, as this generally involves integer multiplication or divide operations.
BCD is very common in electronic systems where a numeric value is to be displayed, especially in systems consisting solely of digital logic, and not containing a microprocessor. By utilizing BCD, the manipulation of numerical data for display can be greatly simplified by treating each digit as a separate single sub-circuit. This matches much more closely the physical reality of display hardware—a designer might choose to use a series of separate identical 7-segment displays to build a metering circuit, for example. If the numeric quantity were stored and manipulated as pure binary, interfacing to such a display would require complex circuitry. Therefore, in cases where the calculations are relatively simple working throughout with BCD can lead to a simpler overall system than converting to 'pure' binary.
The same argument applies when hardware of this type uses an embedded microcontroller or other small processor. Often, smaller code results when representing numbers internally in BCD format, since a conversion from or to binary representation can be expensive on such limited processors. For these applications, some small processors feature BCD arithmetic modes, which assist when writing routines that manipulate BCD quantities.
A widely used variation of the two-digits-per-byte encoding is called packed BCD (or simply packed decimal). All of the upper bytes of a multi-byte word plus the upper four bits (nibble) of the lowest byte are used to store decimal integers. The lower four bits of the lowest byte are used as the sign flag. As an example, a 32 bit word contains 4 bytes or 8 nibbles. Packed BCD uses the upper 7 nibbles to store the integers of a decimal value and uses the lowest nibble to indicate the sign of those integers.
Standard sign values are 1100 (Ch) for positive (+) and 1101 (Dh) for negative (-). Other allowed signs are 1010 (Ah) and 1110 (Eh) for positive and 1011 (Bh) for negative. Some implementations also provide unsigned BCD values with a sign nibble of 1111 (Fh). In packed BCD, the number 127 is represented by "0001 0010 0111 1100" (127Ch) and -127 is represented by "0001 0010 0111 1101 (127Dh).
| Sign Digit | BCD 8 4 2 1 | Sign | Notes |
|---|---|---|---|
| A | 1 0 1 0 | + | |
| B | 1 0 1 1 | − | |
| C | 1 1 0 0 | + | Preferred |
| D | 1 1 0 1 | − | Preferred |
| E | 1 1 1 0 | + | |
| F | 1 1 1 1 | + | Unsigned |
No matter how many bytes wide a word is, there are always an even number of nibbles because each byte has two of them. Therefore, a word of n bytes can contain up to (2n)-1 decimal digits, which is always an odd number of digits. A decimal number with d digits requires ½(d+1) bytes of storage space.
For example, a four-byte (32bit) word can hold seven decimal digits plus a sign, and can represent values ranging from ±9,999,999. Thus the number -1,234,567 is 7 digits wide and is encoded as:
0001 0010 0011 0100 0101 0110 0111 1101
(Note that, like character strings, the first byte of the packed decimal – with the most significant two digits – is usually stored in the lowest address in memory, independent of the endianness of the machine).
In contrast, a four-byte binary two's complement integer can represent values from −2,147,483,648 to +2,147,483,647.
While packed BCD does not make optimal use of storage (about 1/6 of the memory used is wasted), conversion to ASCII, EBCDIC, or the various encodings of Unicode is still trivial, as no arithmetic operations are required. The extra storage requirements are usually offset by the need for the accuracy that fixed-point decimal arithmetic provides. More dense packings of BCD exist which avoid the storage penalty and also need no arithmetic operations for common conversions.
Fixed-point decimal numbers are supported by some programming languages (such as COBOL and PL/I), and provide an implicit decimal point in front of one of the digits. For example, a packed decimal value encoded with the bytes 12 34 56 7C represents the fixed-point value +1,234.567 when the implied decimal point is located between the 4th and 5th digits.
12 34 56 7C
12 34.56 7+
If a decimal digit requires four bits, then three decimal digits require 12 bits. However, since 210 (1,024) is greater than 103 (1,000), if three decimal digits are encoded together, only 10 bits are needed. Two such encodings are Chen-Ho encoding and Densely Packed Decimal. The latter has the advantage that subsets of the encoding encode two digits in the optimal 7 bits and one digit in 4 bits, as in regular BCD.
For signed zoned decimal values, the rightmost (least significant) zone nibble holds the sign digit, which is the same set of values that are used for signed packed decimal numbers (see above). Thus a zoned decimal value encoded as the hex bytes F1 F2 D3 represents the signed decimal value −123:
F1 F2 D3
1 2 −3
| Digit | EBCDIC Display | EBCDIC Hex |
|---|---|---|
| 0+ | { (*) | X'C0' |
| 1+ | A | X'C1' |
| 2+ | B | X'C2' |
| 3+ | C | X'C3' |
| 4+ | D | X'C4' |
| 5+ | E | X'C5' |
| 6+ | F | X'C6' |
| 7+ | G | X'C7' |
| 8+ | H | X'C8' |
| 9+ | I | X'C9' |
| 0− | } (*) | X'D0' |
| 1− | J | X'D1' |
| 2− | K | X'D2' |
| 3− | L | X'D3' |
| 4− | M | X'D4' |
| 5− | N | X'D5' |
| 6− | O | X'D6' |
| 7− | P | X'D7' |
| 8− | Q | X'D8' |
| 9− | R | X'D9' |
(*) Note: These characters vary depending on the local character code page.
Some languages (such as COBOL and PL/I) directly support fixed-point zoned decimal values, assiging an implicit decimal point at some location between the decimal digits of a number. For example, given a six-byte signed zoned decimal value with an implied decimal point to the right of the fourth digit, the hex bytes F1 F2 F7 F9 F5 C0 represent the value +1,279.50:
F1 F2 F7 F9 F5 C0
1 2 7 9. 5 +0
Bit positions in BCD alphamerics were usually labelled B, A, 8, 4, 2 and 1. For encoding digits, B and A were zero. The letter A was encoded (B,A,1).
In the 1620 BCD alphamerics were encoded using digit pairs, with the "zone" in the even digit and the "digit" in the odd digit. Input/Output translation hardware converted between the internal digit pairs and the external standard 6-bit BCD codes.
In the Decimal Architecture IBM 7070, IBM 7072, and IBM 7074 alphamerics were encoded using digit pairs (using two-out-of-five code in the digits, not BCD) of the 10-digit word, with the "zone" in the left digit and the "digit" in the right digit. Input/Output translation hardware converted between the internal digit pairs and the external standard six-bit BCD codes.
With the introduction of System/360, IBM expanded 6-bit BCD alphamerics to 8-bit EBCDIC, allowing the addition of many more characters (e.g., lowercase letters). A variable length Packed BCD numeric data type was also implemented.
Today, BCD data is still heavily used in IBM processors and databases, such as IBM DB2, mainframes, and Power6. In these products, the BCD is usually zoned BCD (as in EBCDIC or ASCII), Packed BCD, or 'pure' BCD encoding. All of these are used within hardware registers and processing units, and in software.
It is possible to perform addition in BCD by first adding in binary, and then converting to BCD afterwards. Conversion of the simple sum of two digits can be done by adding 6 (that is, 16 – 10) when the result has a value of greater-than 9. For example:
However, in BCD, there cannot exist a value greater than 9 (1001) per nibble. To correct this, 6 is added to that sum to get the correct first two digits:
which gives two nibbles, [0001] and [0111] which correspond to "1" and "7" respectively. This gives the 17 in BCD, which is the correct result. This technique can be extended to adding multiple digits, by adding in groups from right to left, propragating the second digit as a carry, always comparing the 5-bit result of a digit-pair sum to 9.
See also Douglas Jones' Tutorial
Subtraction is done by adding the nines' complement plus 1, or by adding the ten's complement of the subtrahend.
The binary-coded decimal scheme described in this article is the most common encoding, but there are many others. The method here can be referred to as Simple Binary-Coded Decimal (SBCD) or BCD 8421. In the headers to the table, the '8 4 2 1', etc., indicates the weight of each bit shown; note that in the 5th column two of the weights are negative. Both ASCII and EBCDIC character codes for the digits are examples of zoned BCD, and are also shown in the table.
The following table represents decimal digits from 0 to 9 in various BCD systems:
| Digit | BCD 8 4 2 1 | Excess-3 or Stibitz Code | BCD 2 4 2 1 or Aiken Code | BCD 8 4 −2 −1 | IBM 702 IBM 705 IBM 7080 IBM 1401 8 4 2 1 | ASCII 0000 8421 | EBCDIC 0000 8421 |
|---|---|---|---|---|---|---|---|
| 0 | 0000 | 0011 | 0000 | 0000 | 1010 | 0011 0000 | 1111 0000 |
| 1 | 0001 | 0100 | 0001 | 0111 | 0001 | 0011 0001 | 1111 0001 |
| 2 | 0010 | 0101 | 0010 | 0110 | 0010 | 0011 0010 | 1111 0010 |
| 3 | 0011 | 0110 | 0011 | 0101 | 0011 | 0011 0011 | 1111 0011 |
| 4 | 0100 | 0111 | 0100 | 0100 | 0100 | 0011 0100 | 1111 0100 |
| 5 | 0101 | 1000 | 1011 | 1011 | 0101 | 0011 0101 | 1111 0101 |
| 6 | 0110 | 1001 | 1100 | 1010 | 0110 | 0011 0110 | 1111 0110 |
| 7 | 0111 | 1010 | 1101 | 1001 | 0111 | 0011 0111 | 1111 0111 |
| 8 | 1000 | 1011 | 1110 | 1000 | 1000 | 0011 1000 | 1111 1000 |
| 9 | 1001 | 1100 | 1111 | 1111 | 1001 | 0011 1001 | 1111 1001 |
In 1972, the U.S. Supreme Court overturned a lower court decision which had allowed a patent for converting BCD encoded numbers to binary on a computer (see Gottschalk v Benson). This was an important case in determining the patentability of software and algorithms.
If error in representation and computation is the primary concern, rather than efficiency of conversion to and from display form, a scaled binary representation may be used, which stores a decimal number as a binary-encoded integer and a binary-encoded signed decimal exponent. For example, 0.2 can be represented as 2. This representation allows rapid multiplication and division, but may require multiplication by a power of 10 during addition and subtraction to align the decimals. It is particularly appropriate for applications with a fixed number of decimal places, which do not require adjustment during addition and subtraction and need not store the exponent explicitly.
Chen-Ho encoding provides a boolean transformation for converting groups of three BCD-encoded digits to and from 10-bit values that can be efficiently encoded in hardware with only 2 or 3 gate delays. Densely Packed Decimal is a similar scheme that deals more efficiently and conveniently with the case where the number of digits is not a multiple of 3.
See also the Decimal Arithmetic Bibliography