逻辑右移和算数右移
逻辑右移:右移后左边添加0
算术右移:右移后添加的位与原数的符号位相同
C语言中,对于移位操作执行的是逻辑左移和算术右移
不过对于无符号类型,所有的移位操作都是逻辑的。
所以要相对一个有符号数执行逻辑右移,那么可以先将它强制类型转换为无符号类型。
如下
int mian()
{
int n = 0xfffffffe;
int m = (unsigned int)n >> 1;
printf("0x%x\n", m);
}
这样右移有可能会产生溢出,变成负数。。。
但是这个计算机系统的datalab,需要把m也变成unsigned,这样所有的样例都通过了
emmmmm底下这一段我没看懂,但是也可以记录一下其他方法:
如果不允许强制类型转换,还要求把有符号数逻辑右移
因为c语言里的>>运算符默认是算术右移(算术右移符号位补位,逻辑右移0补位),所以可以先进行算术右移,再将补位的符号位(可能是0或1)换成0;
假设要逻辑右移n位,就需要将最高位的n位符号位全部替换成0,那么就可以利用左边n位为0,右边32-n位为1的二进制码与算术右移n位后的原码按位与&,便可得到逻辑右移n位后的目标数。
构造这个二进制码可以用:1 << 31得到100...,算术右移n位,得到1...10...0,共n+1位为1。再左移1位,即可得到 1...10...0,共n位为1,再将这个数取反即可。(当然也有其他构造方法)
/*
* logicalShift - shift x to the right by n, using a logical shift
* Can assume that 0 <= n <= 31
* Examples: logicalShift(0x87654321,4) = 0x08765432
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 3
*/
int logicalShift(int x, int n) {
unsigned num1=(unsigned) x;
return num1>>n;
//return ~((((1<<31)&x)>>n)<<1)&(x>>n);
}
今后继续整理算法并写出自己的理解和备注。
C++实现的:二进制中1的个数
1、 二进制中1的个数
int bitCount(int x) {
int res=0;
int var1=0x55|(0x55<<8);
int var2=0x33 |(0x33<<8);
int var3=0x0f |(0x0f<<8);
int var4=0xff|(0xff<<16);
int var5=0xff|(0xff<<8);
var1=var1|(var1<<16);
var2=var2|(var2<<16);
var3=var3|(var3<<16);
res= (x & var1) +((x>>1) & var1);
res= (res &var2) + ((res >>2) &var2);
res= (res &var3) + ((res >>4) &var3);
res= (res &var4) + ((res >>8) &var4);
res= (res &var5) + ((res >>16) &var5);
return res;