6

The value used in my project is expressed with 4-bits binary coded decimals (BCD), which was originally stored in a character buffer (for example, pointed by a pointer const unsigned char *). I want to convert the input BCD char stream to an integer. Would you please show me an efficient and fast way to do that?

Data format example and expected result:

BCD*2; 1001 0111 0110 0101=9765
       "9"  "7"  "6"  "5"

Thank you very much!

chongo2002
  • 131
  • 1
  • 5
  • 12
Golden Lee
  • 95
  • 1
  • 1
  • 4
  • 2
    possible duplicate of [Most efficient way to convert BCD to binary](http://stackoverflow.com/questions/462970/most-efficient-way-to-convert-bcd-to-binary) – Bo Persson May 26 '11 at 12:00
  • @Bo Persson: That posts in C#, not C++ – forsvarir May 26 '11 at 12:06
  • @forsvarir: For the general principle of how to go about this, a C# solution is as good as any other. However, I think my solution is probably more compact than any of the ones in that thread. :-) – C. K. Young May 26 '11 at 12:09

2 Answers2

8
unsigned int lulz(unsigned char const* nybbles, size_t length)
{
    unsigned int result(0);
    while (length--) {
        result = result * 100 + (*nybbles >> 4) * 10 + (*nybbles & 15);
        ++nybbles;
    }
    return result;
}

length here specifies the number of bytes in the input, so for the example given by the OP, nybbles would be {0x97, 0x65} and length would be 2.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • Many thank to Chris Jester-Young. I compared your solution with mine. Your solution is faster. I used "pow" in the while loop. – Golden Lee May 26 '11 at 12:55
5

You can decipher the right-most digit like so:

const unsigned int bcdDigit = bcdNumber & 0xf;

then you can shift the number to the right, so that the next digit becomes the rightmost:

bcdNumber >>= 4;

This will give you the digits in the wrong order though (right to left). If you know how many digits you have, you can of course extract the proper bits directly.

Use e.g. (bcdNumber >> (4 * digitIndex)) & 0xf; to extract the digitIndex:th digit, where digit 0 is the rightmost.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • Dear unwind,
    Thank you for your quick reply. My conversion function template should like this
    unsigned int BCDn( unsigned int n, const unsigned char * data )
    where "const unsigned char *" is a pointer pointed to character buffer for 4-bits binary coded decimals. For example:
    const unsigned char * data = "1001011101100101";
    – Golden Lee May 26 '11 at 12:40