1. Introduction
In this tutorial, we’ll study the binary coded decimal (BCD) format for numbers and go through a few ways to convert BCD to decimal format.
2.1. Definition
BCD is a number system where we represent each decimal digit [0 – 9] by a four-bit binary code or nibble. For example, the BCD representation of the decimal number 14 is 1110. We use BCD in systems that require direct decimal representation for things like digital displays, financial calculations, and timekeeping because these systems allow for more straightforward conversion between decimal and binary forms.
2.2. Mapping
The following table shows decimal to BCD mapping:
| Decimal Digit |
BCD Nibble |
| 0 |
0000 |
| 1 |
0001 |
| 2 |
0010 |
| 3 |
0011 |
| 4 |
0100 |
| 5 |
0101 |
| 6 |
0110 |
| 7 |
0111 |
| 8 |
1000 |
| 9 |
1001 |
2.3. Categories
Based on storage (packing), we categorize BCD into the following two categories:
For the packed variant, we store two BCD nibbles in a single byte. Further, we mostly use a eight-bit register for storage. So, this is an efficient storage since we are utilizing 100% space.
For the unpacked category, each BCD nibble is stored in its own separate register. So, for a eight-bit register, we waste space and hence this type is not optimal.
3. BCD and Pure Binary
BCD is different than pure binary format. In binary format, we process number as a whole to give a single binary value. In BCD case, we represent each digit in the number as a BCD nibble. For example, binary form of 15 is 1111 where as its BCD numeral is 0001 0101.
4. BCD to Decimal Conversion by Bitwise Operations
This is the most intuitive method to change a single packed BCD byte (8 bits) into its decimal equivalent.
In this appraoch, we use bitwise operations over the byte that holds both the BCD nibbles.
To do this, we use the upper 4 bits for the tens place, and the lower 4 bits for the units place. First, we right-shift (>>) to move the upper nibble into the lower position, and then do a bitwise AND (&) to isolate the four relevant bits and mask out the rest:
public static int convertPackedByte(byte bcdByte) {
int upperNibble = (bcdByte >> 4) & 0x0F;
int lowerNibble = bcdByte & 0x0F;
if (upperNibble > 9 || lowerNibble > 9) {
throw new IllegalArgumentException(
String.format("Invalid BCD format: byte 0x%02X contains non-decimal digit.", bcdByte)
);
}
int resultDecimal = upperNibble * 10 + lowerNibble;
return resultDecimal;
}
As evident, this method is highly efficient for single-byte packed BCD values.
Now, let’s test this method:
@Test
void testConvertPackedByteValidValues() {
// Test 05 (0x05) ->
assertEquals(5, BCDtoDecimalConverter.convertPackedByte((byte) 0x05));
// Test 22 (0x22) -> 22
assertEquals(22, BCDtoDecimalConverter.convertPackedByte((byte) 0x22));
// Test 97 (0x97) -> 97
assertEquals(97, BCDtoDecimalConverter.convertPackedByte((byte) 0x97));
}
5. BCD to Decimal Conversion by Arrays
For larger decimal numbers, we use array to store BCD values because arrays allow us to store nibbles across multiple bytes. For conversion, we iterate through each byte, apply the bitwise logic as per last section, and iteratively build our decimal result:
public static long convertPackedByteArray(byte[] bcdArray) {
long resultDecimal = 0;
for (byte bcd : bcdArray) {
int upperNibble = (bcd >> 4) & 0x0F;
int lowerNibble = bcd & 0x0F;
if (upperNibble > 9 || lowerNibble > 9) {
throw new IllegalArgumentException("Invalid BCD format: nibble contains non-decimal digit.");
}
resultDecimal = resultDecimal * 100 + (upperNibble * 10 + lowerNibble);
}
return resultDecimal;
}
Next, we see convertPackedByte() in action by running the following test code:
@Test
void testConvertPackedByteArrayValidValues() {
// Test 0 -> [0x00]
assertEquals(0L, BCDtoDecimalConverter.convertPackedByteArray(new byte[]{(byte) 0x00}));
// Test 99 -> [0x99]
assertEquals(99L, BCDtoDecimalConverter.convertPackedByteArray(new byte[]{(byte) 0x99}));
// Test 1234 -> [0x12, 0x34]
byte[] bcd1234 = {(byte) 0x12, (byte) 0x34};
assertEquals(1234L, BCDtoDecimalConverter.convertPackedByteArray(bcd1234));
// Test 12345678 -> [0x12, 0x34, 0x56, 0x78]
byte[] bcdLarge = {(byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78};
assertEquals(12345678L, BCDtoDecimalConverter.convertPackedByteArray(bcdLarge));
}
6. Conclusion
In this article, we’ve studied BCD number format and couple of ways to convert it to decimal number system.
Owing to diversity in application needs and user inputs, we often need number format conversion. In Java, BCD to decimal format conversion is a common task and we can do in a many ways. We can use either bitwise operations or array processing. Both these methods decode BCD by extracting and combining these 4-bit nibbles.
The code for this article is available over on GitHub.