Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

8-digit BCD check

Tags:

c++

c

bcd

I've a 8-digit BCD number and need to check it out to see if it is a valid BCD number. How can I programmatically (C/C++) make this?

Ex: 0x12345678 is valid, but 0x00f00abc isn't.

Thanks in advance!

like image 458
Fernanda Brum Lousada Avatar asked Jun 12 '26 10:06

Fernanda Brum Lousada


2 Answers

You need to check each 4-bit quantity to make sure it's less than 10. For efficiency you want to work on as many bits as you can at a single time.

Here I break the digits apart to leave a zero between each one, then add 6 to each and check for overflow.

uint32_t highs = (value & 0xf0f0f0f0) >> 4;
uint32_t lows = value & 0x0f0f0f0f;
bool invalid = (((highs + 0x06060606) | (lows + 0x06060606)) & 0xf0f0f0f0) != 0;

Edit: actually we can do slightly better. It doesn't take 4 bits to detect overflow, only 1. If we divide all the digits by 2, it frees a bit and we can check all the digits at once.

uint32_t halfdigits = (value >> 1) & 0x77777777;
bool invalid = ((halfdigits + 0x33333333) & 0x88888888) != 0;
like image 61
Mark Ransom Avatar answered Jun 15 '26 00:06

Mark Ransom


The obvious way to do this is:

/* returns 1 if x is valid BCD */
int
isvalidbcd (uint32_t x)
{
    for (; x; x = x>>4)
    {
        if ((x & 0xf) >= 0xa)
            return 0;
    }
    return 1;
}

This link tells you all about BCD, and recommends something like this asa more optimised solution (reworking to check all the digits, and hence using a 64 bit data type, and untested):

/* returns 1 if x is valid BCD */
int
isvalidbcd (uint32_t x)
{
   return !!(((uint64_t)x + 0x66666666ULL) ^ (uint64_t)x) & 0x111111110ULL;
}
like image 28
abligh Avatar answered Jun 15 '26 00:06

abligh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!