我正在将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数字转换成十进制?
发布于 2013-07-23 13:12:19
如下所示,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;
}
}还要注意(在所有版本中,包括原始版本),您可能会留下一个新的数字进位。
发布于 2013-07-23 13:28:45
您必须重新设计函数,使其包含要移位的位数,作为argument.And使用该参数将bcd字节移位许多位置。
void LShift(unsigned char *arg) can be modified to void LShift(unsigned char *arg,int n)并这样做
temp=(arg[i]<<n)+carry;发布于 2013-07-23 14:56:03
编写移位逻辑有点复杂,因为进位操作有点繁琐。它变成了看起来非常像移位和加法乘法实现的代码。
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转换到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;
}
}https://stackoverflow.com/questions/17801770
复制相似问题