我将BCD数字的位向左或向右移动以快速乘法或除以2.这是左移的一个简单示例:
void LShift(unsigned char *arg)
{
int i, carry=0, temp;
for(i=2;i>=0;i--)
{
temp=(arg[i]<<1)+carry;
if (temp>9) temp+=6;
carry=temp>>4;
arg[i]=temp&0xF;
}
}
这很好用,如果你给它一个类似{4,5,6}
的数组,它将返回{9,1,2}.
问题是,如果我想要移位多于一位,我必须调用该函数并且过度。有没有一种聪明的方法可以一次移动多个位而不先将BCD数转换为十进制数?
答案 0 :(得分:2)
见下文,N是要移位的位数,假设N <= 3,如果移位超过3(N> 3),则需要处理多于一位的进位(例如9 * (2 ^ 4)= 144):
void LShift(unsigned char *arg)
{
int i, carry=0, temp;
for(i=2;i>=0;i--)
{
temp=(arg[i]<<N)+carry;
arg[i]=temp%10;
temp -= arg[i];
carry = temp/10;
}
}
或者如果你想要更接近原作的东西:
void LShift(unsigned char *arg)
{
int i, carry=0, temp;
for(i=2;i>=0;i--)
{
temp=(arg[i]<<N)+carry;
temp+=6 * (temp/10);
carry=temp>>4;
arg[i]=temp&0xF;
}
}
另请注意(在所有版本中,包括原件),您可能会留下一个新的数字。
答案 1 :(得分:1)
您必须重新设计函数以包含要作为参数移位的位数。并使用该参数将bcd字节移位多个位置。
void LShift(unsigned char *arg) can be modified to void LShift(unsigned char *arg,int n)
并做
temp=(arg[i]<<n)+carry;
答案 2 :(得分:0)
编码移位逻辑有点复杂,因为进位操作有点毛茸茸。它变成了看起来非常像移位和添加乘法实现的代码。
void LeftShiftN_1 (unsigned char arg[BCD_DIGITS], unsigned N) {
int i, j;
unsigned x, carry;
unsigned char accum[BCD_DIGITS];
memset(accum, '\0', sizeof(carry));
for (i=BCD_DIGITS; i>0; --i) {
x = arg[i-1];
x <<= N;
carry = 0;
for (j=i; j>=0; --j) {
carry += accum[j-1] + x % 10;
x /= 10;
accum[j-1] = carry % 10;
carry /= 10;
}
}
memcpy(arg, accum, sizeof(accum));
}
我认为从BCD转换然后再转换到转换更简单有效。我以直截了当的方式实现,我确信转换操作可以进行优化。
void LeftShiftN_2 (unsigned char arg[BCD_DIGITS], unsigned N) {
int i;
unsigned accum;
accum = 0;
for (i=0; i<BCD_DIGITS; ++i) {
accum = 10*accum + arg[i];
}
accum <<= N;
for (i=BCD_DIGITS; i>0; --i) {
arg[i-1] = accum % 10;
accum /= 10;
}
}