需要使用按位运算符移动数字位?
need to shift bits in number using bitwise operators?
#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");
}
我需要交换数字中的 (m 到 m-t) 和 (n 到 nt) 的位 num.I 尝试了上面的代码,但它不起作用..有人可以帮忙吗?
如果你把它分解成更小的步骤会更容易。
首先,制作一个t位宽的位掩码。您可以通过从 2 的幂中减去 1 来实现,如下所示:
int mask = (1 << t) - 1;
例如,如果 t 为 3,则掩码将为 7(二进制为 111)。
然后你可以复制 num 并清除 m 到 m-t 和 n 到 n-t 范围内的位,方法是向上移动掩码,NOT 和 ANDing,这样只有掩码未覆盖的位保持设置:
res = num & ~(mask<<(m-t)) & ~(mask<<(n-t));
然后你可以将两个范围内的位移动到它们适当的位置,并与结果进行或运算。您可以通过向下移动 (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);
如果两个范围重叠,这将不起作用。目前尚不清楚在这种情况下正确的行为是什么。
与位交换问题一样,您可以使用异或来节省一些指令。
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);
}
#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");
}
我需要交换数字中的 (m 到 m-t) 和 (n 到 nt) 的位 num.I 尝试了上面的代码,但它不起作用..有人可以帮忙吗?
如果你把它分解成更小的步骤会更容易。
首先,制作一个t位宽的位掩码。您可以通过从 2 的幂中减去 1 来实现,如下所示:
int mask = (1 << t) - 1;
例如,如果 t 为 3,则掩码将为 7(二进制为 111)。
然后你可以复制 num 并清除 m 到 m-t 和 n 到 n-t 范围内的位,方法是向上移动掩码,NOT 和 ANDing,这样只有掩码未覆盖的位保持设置:
res = num & ~(mask<<(m-t)) & ~(mask<<(n-t));
然后你可以将两个范围内的位移动到它们适当的位置,并与结果进行或运算。您可以通过向下移动 (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);
如果两个范围重叠,这将不起作用。目前尚不清楚在这种情况下正确的行为是什么。
与位交换问题一样,您可以使用异或来节省一些指令。
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);
}