目录
1、左移<<(不分有符号和无符号,这一点与右移不同)
要点1:忽略左边任何位包括符号位置,右边补0;例如,1往左移动31位,则符号位变为1,于是变成了int中最小的负整数;
要点2:如果移动的位数超过了int的最大可移动位数31位,那么编译器会对移动的位数取模。如对int型移动33位,实际上只移动了33%32=1位。
要点3:当移动前后移动后取值都在有效值范围内时,左移动一位相当于值*2,右移动一位相当于除以2(即左右移动的时候没有丢失有效位1的前提下成立)。很多地方没有加上最前面这个条件,导致很多学员一头雾水(举出了一堆反例,比如3左移30位得到-1073741824);
1)打印1的所有二进制位
System.out.println(printBit(1));
00000000000000000000000000000001
2)打印1左移31位后的所有二进制位和10进制数值;
System.out.println(printBit(1<<31));
10000000000000000000000000000000
System.out.println(1<<31);
-2147483648
2)打印1左移32位后的所有二进制位和10进制数值;
System.out.println(printBit(1<<32));
System.out.println(1<<32);
00000000000000000000000000000001
1
3)打印1左移33位后的所有二进制位和10进制数值;
System.out.println(printBit(1<<33));
System.out.println(1<<33);
00000000000000000000000000000010
4)如果是负数,是否也满足左移动乘2的规律,这里做一下细细的分析;
首先找一个左边第二位非0的负数(如果左边第二位是0,那么这个负数(取反+1)*2的绝对值超出了负数的绝对值范围);假设整数只有8位,例子如下:
从上面可以看出,只要负数在取值范围内,仍然满足左移一位等于值*2的规律;
2、右移:分为带符号右移>>和不带符号右移>>>
1)带符号右移>>:右移之后,左边的补上符号位,正数补0,负数补1
2)无符号右移位>>>,不管正数还是负数,高位都用0补齐(忽略符号位);
3)举例如下:
System.out.println(printBit(Integer.MIN_VALUE));
System.out.println(printBit(Integer.MIN_VALUE>>1));
System.out.println(printBit(Integer.MIN_VALUE>>>1));
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MIN_VALUE>>1);
System.out.println(Integer.MIN_VALUE>>>1);
Integer.MIN_VALUE: 10000000000000000000000000000000
Integer.MIN_VALUE>>1: 11000000000000000000000000000000
Integer.MIN_VALUE>>>1:01000000000000000000000000000000
Integer.MIN_VALUE:-2147483648
Integer.MIN_VALUE>>1:-1073741824
Integer.MIN_VALUE>>>1:1073741824
=================================
4)同样的道理,右移动相当于除以2,也是不能超出数据类型的范围才成立;
3、相关面试题让你更加融会贯通
1)统计二进制中1的个数
解法1:
public static int getBitCount1(int num){
int count = 0;
for(int i=31;i>=0;i--){
if((num>>i & 1) == 1){
count++;
}
}
return count;
}
解法2:
public static int getBitCount2(int num){
int count = 0;
for(int i=31;i>=0;i--){
if((1< 0){
count++;
}
}
return count;
}
分析:以上两个解法中,解法2是有问题的,当num为负数时,1左移31位后与num位与后为10000000...,是负数不大于0;应该改为:if((1<
2)判断输入整数是否为2的幂
解法1:
public static boolean ifTwoPow(int num){
boolean flag = true;
while(num!=1){
if(num<=0 || num%2!=0){
flag = false;
break;
}
num=num>>1;
}
return flag;
}
解法2:
public static boolean ifTwoPow2(int num){
//解释:与运算为0,说明最高位的1变为了0,最高位的1因为减去1的操作都被拿来用了,说明后面全是0不够减,哈哈机智如我
return (num & (num-1)) == 0;
}