#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)的位。我尝试了上面的代码,但它没有工作......有人可以帮忙。
答案 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);
}