需要使用按位运算符来移位位数?

时间:2015-10-28 13:00:36

标签: bit-manipulation

#include<stdio.h>
int main()
{
    int num,m,n,t,res,i;
    printf("Enter number\n");
    scanf("%d",&num);
    for(i=31;i>=0;i--)
    {
        printf("%d",((num>>i)&1));
    }
    printf("\n");
    printf("Enter position 1 and position 2\n");
    scanf("%d%d",&m,&n);
    printf("enter number\n");
    scanf("%d",&t);

    res=((num&(~(((~(unsigned)0)>>(32-((m-t)+1)))<<t)))&(num&(~(((~(unsigned)0)>>(32-((n-t)+1)))<<t))))|(((((num&((((~(unsigned)0)>>(((m-t))))<<(n))))>>(m-t))))|(((num&((((~(unsigned)0)>>(((32-n))))<<(32-t))))<<(m-t))));

    for(i=31;i>=0;i--)
    {
         printf("%d",(res>>i)&1);
    }
    printf("\n");
}

我需要在数字num中交换(m到m-t)和(n到n-t)的位。我尝试了上面的代码,但它没有工作......有人可以帮忙。

2 个答案:

答案 0 :(得分:0)

如果将其分解为更小的步骤,情况会更容易。

首先,将位掩码设为t位宽。你可以通过从2的幂减去1来做到这一点,如下所示:

int mask = (1 << t) - 1;

例如,如果t为3,则掩码为7(二进制为111)。

然后你可以复制num并清除m到mt和n到nt范围内的位,方法是向上移动掩码,注意它和ANDing,这样只有未被掩码覆盖的位才会被设置:< / p>

res = num & ~(mask<<(m-t)) & ~(mask<<(n-t));

然后,您可以将两个范围中的位移动到适当的位置,并将结果与​​OR相关联。您可以通过向下移动(n-t),屏蔽,然后向上移动(m-t)来完成此操作,反之亦然:

res |= ((num >> (n-t)) & mask) << (m-t);
res |= ((num >> (m-t)) & mask) << (n-t);

这些位现在位于正确的位置。

你可以在一行中这样做:

res = (num & ~(mask<<(m-t)) & ~(mask<<(n-t))) | (((num >> (n-t)) & mask) << (m-t)) | (((num >> (m-t)) & mask) << (n-t));

可以通过事先进行m-t和n-t减法来简化它,假设你不想在之后使用这些值:

m -= t; n -= t;
res = (num & ~(mask<<m) & ~(mask<<n)) | (((num >> n)) & mask) << m) | (((num >> m) & mask) << n);

如果两个范围重叠,则不起作用。在这种情况下,不清楚正确的行为是什么。

答案 1 :(得分:0)

与通常的位交换问题一样,您可以使用xor保存一些指令。

unsigned f(unsigned num, unsigned n, unsigned m, unsigned t) {
    n -= t; m -= t;
    unsigned mask = ((unsigned) 1 << t) - 1;
    unsigned nm = ((num >> n) ^ (num >> m)) & mask;
    return num ^ (nm << n) ^ (nm << m);
}