我有一个8位的BCD号码,需要检查一下它是否是一个有效的BCD号码。我如何以编程方式(C/C++)实现这一点?
例如: 0x12345678有效,但0x00f00abc无效。
提前感谢!
发布于 2015-03-21 05:27:34
你需要检查每个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;发布于 2015-03-21 05:30:53
最明显的方法是:
/* 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;
}发布于 2015-03-21 07:33:39
对于无效的数字,它需要是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个不同的遮罩。
https://stackoverflow.com/questions/29175568
复制相似问题