位运算是直接可以操纵数据的二进制,在运算方面大大减少了内存的负担,使程序运行速度大大提升。所以巧妙的运用位运算可以使程序的运行效率提升不止一个档次。
常见的位运算有:
1、>>右移运算符。将数的二进制形式下最后一位去除,剩下的一次右移。如果是正数,最高位就补0,如果是负数,最高位就补1(一般强情况,也有可能补0)。产生的效果,给这个数除2.
2、<<左移运算符。将数的二进制形式下的最高位去掉,其他数字一次左移,最低位补0。产生效果,给这个数乘2.
3.&:按位与。将二进制的两个数按位进行与运算,全部是1才是1,否则是0。
4.|:按位或。将二进制的两个数按位进行或运算,全部是0才是0,否则是1.
5.!:按位取反:将二进制每一位按位取反。
常见的运算就是以上几种,但是即使是这么简单的几种,也可以产生神奇的效果。
效果1:
判断一个数是不是2的整数次方:
if(n&(n-1)==0){
是二的整数次方
}else{
不是。
}
(n&(n-1))的作用就是去除从右往左数第一个1。2的整数次方只可能有一个1,所以去掉之后就变成0了。
这个方法还能运用在统计一个数的二进制中有多少个1.
方法就是每次去除一个1,统计加1。一直到数为0,就能得到有多少个1了。
效果2:
利用右移除2和左移乘2的特性。
实现Pow函数,即得到任意数的整数次方是多少。
根据公式
n^m:
(1)m是奇数:=n^(m/2)*n^(m/2)*n:
(2)m是偶数:=n^(m/2)*n(m/2);
将n^(m/2)看做一个数。则就是给这个数开平方。利用分治的思想一层层递归下去,能达到用log(n)的时间复杂度求解出这个问题。
则代码实现:int getMathSquare(double n,int m){
if(m==0){
return 1;
}
if(m==1){
return n;
}
double result = getMathSquare(n,m>>1)
result*=result;
if(m&1==1){//看当前的指数是否是奇数
result*=n;
}
return result;
}
以上代码用右移代表除2,用m&1==1代替了取余。大大提高了程序的效率。
所有可以再适当的情况下,合理运用位运算。