0.基础
位运算是以二进制为单位进行的运算,其操作数和运算结果都是整型值。
右移是将一个二进制数按指定移动的位数向右移位,移掉的被丢弃,左边移进的部分或者补0(当该数为正),或者补1(当该数为负),这是因为整数在机器内部采用补码表示法,整数的符号位为0,负数的符号位为1.
1.如何用移位操作实现乘法运算
把一个数向左移动n位相当于把该数乘以2的n次方,因此当乘法运算中某个数字满足这个特点时,就可以用移位操作来代替乘法操作,eg:
public class Muti {
public static int powerN(int m,int n){//m乘以2的n次方
for(int i=0;i<n;i++){
m=m<<1;
}
return m;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("3*8="+powerN(3,3));
System.out.println("3*16="+powerN(3,4));
}
}
/*
3*8=24
3*16=48
*/
2.如何判断一个数是否为2的n次方
方法一:用1作移位操作,判断移位后的值是否与给定的数相等,算法的复杂度为O(longn)
方法二:2^0、2^1、2^2……二进制分别为1/10/100……,如果一个数是2的n次方,那么这个数对应的二进制表示中只有一位是1,其余都为0。eg:num=01000000,那么num-1=00111111,因此num&(num-1)运算结果为0
public class TestTwon {
public static boolean isPower(int n){
if(n<1){
return false;
}
int i=1;
while(i<=n){
if(i==n){
return true;
}
i<<=1;
}
return false;
}
public static boolean isPowerTwo(int n){
if(n<1){
return false;
}
int m=n&(n-1);
return m==0;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(isPower(4));
System.out.println(isPower(6));
System.out.println(isPowerTwo(4));
System.out.println(isPowerTwo(6));
}
}
3.求二进制数中1的个数
方法一:首先,判断这个数的最后一位是否为1,如果为1则计数器加1,然后通过右移丢弃掉最后一位。循环执行该操作直到这个数等于0为止。时间复杂度为O(n),其中n为二进制的位数
方法二:只考虑1的个数,把二进制表示中每个1看做独立的个体,利用2中思想求出1的个数,给定一个数n,每进行一次n&(n-1)计算,其结果中都会少一位1,而且是最后一位。时间复杂度为O(m),m为二进制中1的个数
public class CountOne {
public static int countOne(int n){
int count=0;
while(n>0){
if((n&1)==1){
count++;
}
n>>=1;
}
return count;
}
public static int countOneBetter(int n){
int count=0;
while(n>0){
if(n!=0){
n=n&(n-1);
count++;
}
}
return count;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(countOne(7));
System.out.println(countOne(8));
System.out.println(countOneBetter(10));
}
}