8位BCD检查

时间:2015-03-20 20:49:00

标签: c++ c bcd

我有一个8位数的BCD号码,需要查看它是否是有效的BCD号码。我怎样才能以编程方式(C / C ++)制作这个?

Ex:0x12345678有效,但0x00f00abc不是。

提前致谢!

4 个答案:

答案 0 :(得分:10)

您需要检查每个4位数量,以确保它小于10.为了提高效率,您希望一次只能处理多少位。

这里我将数字分开以在每个数字之间留下零,然后每个数字加6并检查溢出。

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

编辑:实际上我们可以做得更好。它不需要4位来检测溢出,只有1.如果我们将所有数字除以2,它会释放一些,我们可以一次检查所有数字。

uint32_t halfdigits = (value >> 1) & 0x77777777;
bool invalid = ((halfdigits + 0x33333333) & 0x88888888) != 0;

答案 1 :(得分:3)

显而易见的方法是:

/* 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告诉你关于BCD的所有内容,并推荐这样的更优化的解决方案(重新检查所有数字,因此使用64位数据类型,并且未经测试):

/* returns 1 if x is valid BCD */
int
isvalidbcd (uint32_t x)
{
   return !!(((uint64_t)x + 0x66666666ULL) ^ (uint64_t)x) & 0x111111110ULL;
}

答案 2 :(得分:3)

要使数字无效,则需要为10-15。这反过来意味着8 + 4或8 + 2 - 低位根本不重要。

所以:

long mask8 = value & 0x88888888;
long mask4 = value & 0x44444444;
long mask2 = value & 0x22222222;
return ((mask8 >> 2) & ((mask4 >>1) | mask2) == 0;

略显不明显:

long mask8 = (value>>2);
long mask42 = (value | (value>>1);
return (mask8 & mask42 & 0x22222222) == 0;

通过在遮蔽前移动,我们不需要3个不同的遮罩。

答案 3 :(得分:2)

@Mark Ransom启发

 bool invalid = (0x88888888 & (((value & 0xEEEEEEEE) >> 1) + (0x66666666 >> 1))) != 0;
 // or
 bool valid = !((((value & 0xEEEEEEEEu) >> 1) + 0x33333333) & 0x88888888);

屏蔽每个BCD数字1的位置,右移,然后加6并检查BCD数字溢出。


这是如何工作的:
通过向每个数字添加+6,我们会查找4位数字的溢出*

 abcd
+ 110
-----
*efgd

但是d的位值对总和没有贡献,因此首先屏蔽该位并向右移位。现在溢出位位于8's位置。这一切都是并行完成的,我们用0x88888888屏蔽这些进位,并测试是否有任何设置。

 0abc
+  11
-----
 *efg