优秀程序员不得不知道的20个位运算技巧

目录(?)[+]

  1. 获得int型最大值
    1. 另一种写法
    2. 另一种写法
    3. C语言中不知道int占几个字节时候
  2. 获得int型最小值
    1. 另一种写法
  3. 获得long类型的最大值
    1. C语言版
    2. JAVA版
  4. 乘以2运算
  5. 除以2运算
  6. 乘以2的m次方
  7. 除以2的m次方
  8. 判断一个数的奇偶性
  9. 不用临时变量交换两个数面试常考
    1. C语言版
    2. 通用版一些语言中得分开写
  10. 取绝对值某些机器上效率比n0 n-n 高
  11. 取两个数的最大值某些机器上效率比ab ab高
    1. 通用版
    2. C语言版
  12. 取两个数的最小值某些机器上效率比ab ba高
    1. 通用版
    2. C语言版
  13. 判断符号是否相同
  14. 计算2的n次方
  15. 判断一个数是不是2的幂
  16. 对2的n次方取余
  17. 求两个整数的平均值
    1. 另一种写法
  18. 从低位到高位取n的第m位
  19. 从低位到高位将n的第m位置1
  20. 从低位到高位将n的第m位置0
  21. 另附一些对程序效率上没有实质提高的位运算技巧一些也是位运算的常识面试也许会遇到
    1. 计算n1
    2. 计算n-1
    3. 取相反数
      1. 另一种写法
    4. ifx a x b ifx b x a
    5. sign函数参数为n当n0时候返回1n0时返回-1n0时返回0

      一提起位运算,人们往往想到它的高效性,无论是嵌入式编程还是优化系统的核心代码,适当的运用位运算总是一种迷人的手段,或者当您求职的时候,在代码中写入适当的位运算也会让您的程序增加一丝亮点,最初当我读《编程之美》求“1的数目”时,我才开始觉得位运算是如此之美,后来读到 《Hacker's Delight》,感慨到Henry S.Warren把位运算运用的如此神出鬼没,很多程序都十分精妙,我觉得在一个普通的程序中大量运用这样的代码的人简直是疯了!但掌握简单的位运算技巧还是必要的,所以今天写这篇博文把我积累的一些位运算技巧分享给大家,这些技巧不会是如求“1的数目”的技巧,是最基本的一行位运算技巧


Welcome To My BitTricks

1.获得int型最大值

  1. int getMaxInt(){  
  2.         return (1 << 31) - 1;//2147483647, 由于优先级关系,括号不可省略   
  3. }  
int getMaxInt(){
        return (1 << 31) - 1;//2147483647, 由于优先级关系,括号不可省略
}

 

另一种写法

  1. int getMaxInt(){  
  2.     return ~(1 << 31);//2147483647   
  3. }  
int getMaxInt(){
	return ~(1 << 31);//2147483647
}

另一种写法

  1. int getMaxInt(){//有些编译器不适用   
  2.     return (1 << -1) - 1;//2147483647   
  3. }  
int getMaxInt(){//有些编译器不适用
	return (1 << -1) - 1;//2147483647
}

C语言中不知道int占几个字节时候

  1. int getMaxInt(){  
  2.     return ((unsigned int) - 1) >> 1;//2147483647   
  3. }  
int getMaxInt(){
	return ((unsigned int) - 1) >> 1;//2147483647
}

2.获得int型最小值

  1. int getMinInt(){  
  2.     return 1 << 31;//-2147483648   
  3.  }  
int getMinInt(){
	return 1 << 31;//-2147483648
 }

另一种写法

  1. int getMinInt(){//有些编译器不适用   
  2.     return 1 << -1;//-2147483648   
  3. }  
int getMinInt(){//有些编译器不适用
	return 1 << -1;//-2147483648
}

3.获得long类型的最大值


C语言版

  1. long getMaxLong(){  
  2.     return ((unsigned long) - 1) >> 1;//2147483647   
  3. }  
long getMaxLong(){
	return ((unsigned long) - 1) >> 1;//2147483647
}

JAVA版

  1. long getMaxLong(){  
  2.     return ((long)1 << 127) - 1;//9223372036854775807   
  3. }  
long getMaxLong(){
	return ((long)1 << 127) - 1;//9223372036854775807
}
获得long最小值,和其他类型的最大值,最小值同理.

4.乘以2运算

  1. int mulTwo(int n){//计算n*2    
  2.     return n << 1;  
  3. }  
int mulTwo(int n){//计算n*2 
	return n << 1;
}

5.除以2运算

  1. int divTwo(int n){//负奇数的运算不可用   
  2.     return n >> 1;//除以2   
  3. }  
int divTwo(int n){//负奇数的运算不可用
	return n >> 1;//除以2
}

6.乘以2的m次方

  1. int mulTwoPower(int n,int m){//计算n*(2^m)   
  2.     return n << m;  
  3. }  
int mulTwoPower(int n,int m){//计算n*(2^m)
	return n << m;
}

7.除以2的m次方

  1. int divTwoPower(int n,int m){//计算n/(2^m)   
  2.     return n >> m;  
  3. }  
int divTwoPower(int n,int m){//计算n/(2^m)
	return n >> m;
}

8.判断一个数的奇偶性

  1. boolean isOddNumber(int n){  
  2.     return (n & 1) == 1;  
  3. }  
boolean isOddNumber(int n){
	return (n & 1) == 1;
}

9.不用临时变量交换两个数(面试常考)


C语言

  1. void swap(int *a,int *b){     
  2.     (*a) ^= (*b) ^= (*a) ^= (*b);     
  3. }  
void swap(int *a,int *b){	
	(*a) ^= (*b) ^= (*a) ^= (*b);	
}

通用版(一些语言中得分开写)

  1. a ^= b;  
  2. b ^= a;  
  3. a ^= b;  
a ^= b;
b ^= a;
a ^= b;

10.取绝对值(某些机器上效率比n>0  ?  n:-n 高)

  1. int abs(int n){  
  2. return (n ^ (n >> 31)) - (n >> 31);  
  3. /* n>>31 取得n的符号,若n为正数,n>>31等于0,若n为负数,n>>31等于-1 
  4. 若n为正数 n^0=0,数不变,若n为负数有n^-1 需要计算n和-1的补码,然后进行异或运算, 
  5. 结果n变号并且为n的绝对值减1,再减去-1就是绝对值 */  
  6. }  
int abs(int n){
return (n ^ (n >> 31)) - (n >> 31);
/* n>>31 取得n的符号,若n为正数,n>>31等于0,若n为负数,n>>31等于-1
若n为正数 n^0=0,数不变,若n为负数有n^-1 需要计算n和-1的补码,然后进行异或运算,
结果n变号并且为n的绝对值减1,再减去-1就是绝对值 */
}

11.取两个数的最大值(某些机器上,效率比a>b ? a:b高)


通用版

  1. int max(int a,int b){  
  2.     return b & ((a-b) >> 31) | a & (~(a-b) >> 31);  
  3.     /*如果a>=b,(a-b)>>31为0,否则为-1*/  
  4. }  
int max(int a,int b){
	return b & ((a-b) >> 31) | a & (~(a-b) >> 31);
	/*如果a>=b,(a-b)>>31为0,否则为-1*/
}

C语言版

  1. int max(int x,int y){  
  2.     return x ^ ((x ^ y) & -(x < y));  
  3.     /*如果x<y x<y返回1,否则返回0, 
  4. 、 与0做与运算结果为0,与-1做与运算结果不变*/  
  5. }  
int max(int x,int y){
	return x ^ ((x ^ y) & -(x < y));
	/*如果x<y x<y返回1,否则返回0,
、 与0做与运算结果为0,与-1做与运算结果不变*/
}

12.取两个数的最小值(某些机器上,效率比a>b ? b:a高)


通用版

  1. int min(int a,int b){  
  2.     return a & ((a-b) >> 31) | b & (~(a-b) >> 31);  
  3.     /*如果a>=b,(a-b)>>31为0,否则为-1*/  
  4. }  
int min(int a,int b){
	return a & ((a-b) >> 31) | b & (~(a-b) >> 31);
	/*如果a>=b,(a-b)>>31为0,否则为-1*/
}

C语言版

  1. int min(int x,int y){  
  2.     return y ^ ((x ^ y) & -(x < y));  
  3.          /*如果x<y x<y返回1,否则返回0, 
  4.             与0做与运算结果为0,与-1做与运算结果不变*/  
  5. }  
int min(int x,int y){
	return y ^ ((x ^ y) & -(x < y));
         /*如果x<y x<y返回1,否则返回0,
            与0做与运算结果为0,与-1做与运算结果不变*/
}

13.判断符号是否相同

  1. boolean isSameSign(int x, int y){ //有0的情况例外   
  2.     return (x ^ y) >= 0// true 表示 x和y有相同的符号, false表示x,y有相反的符号。   
  3. }  
boolean isSameSign(int x, int y){ //有0的情况例外
	return (x ^ y) >= 0; // true 表示 x和y有相同的符号, false表示x,y有相反的符号。
}

14.计算2的n次方

  1. int getFactorialofTwo(int n){//n > 0   
  2.     return 2 << (n-1);//2的n次方   
  3. }  
int getFactorialofTwo(int n){//n > 0
	return 2 << (n-1);//2的n次方
}

15.判断一个数是不是2的幂

  1. boolean isFactorialofTwo(int n){  
  2.     return n > 0 ? (n & (n - 1)) == 0 : false;  
  3.     /*如果是2的幂,n一定是100... n-1就是1111.... 
  4.        所以做与运算结果为0*/  
  5. }  
boolean isFactorialofTwo(int n){
	return n > 0 ? (n & (n - 1)) == 0 : false;
	/*如果是2的幂,n一定是100... n-1就是1111....
	   所以做与运算结果为0*/
}

16.对2的n次方取余

  1. int quyu(int m,int n){//n为2的次方   
  2.     return m & (n - 1);  
  3.     /*如果是2的幂,n一定是100... n-1就是1111.... 
  4.      所以做与运算结果保留m在n范围的非0的位*/  
  5. }  
int quyu(int m,int n){//n为2的次方
	return m & (n - 1);
	/*如果是2的幂,n一定是100... n-1就是1111....
	 所以做与运算结果保留m在n范围的非0的位*/
}

17.求两个整数的平均值

  1. int getAverage(int x, int y){  
  2.         return (x + y) >> 1;   
  3. }  
int getAverage(int x, int y){
        return (x + y) >> 1; 
}

另一种写法

  1. int getAverage(int x, int y){  
  2.         return ((x ^ y) >> 1) + (x & y);   
  3.      /*(x^y) >> 1得到x,y其中一个为1的位并除以2, 
  4.        x&y得到x,y都为1的部分,加一起就是平均数了*/  
  5.   
  6. }   
int getAverage(int x, int y){
        return ((x ^ y) >> 1) + (x & y); 
     /*(x^y) >> 1得到x,y其中一个为1的位并除以2,
       x&y得到x,y都为1的部分,加一起就是平均数了*/

} 

下面是三个最基本对二进制位的操作

18.从低位到高位,取n的第m位

  1. int getBit(int n, int m){  
  2.     return (n >> (m-1)) & 1;  
  3. }  
int getBit(int n, int m){
	return (n >> (m-1)) & 1;
}

19.从低位到高位.将n的第m位置1

  1. int setBitToOne(int n, int m){  
  2.     return n | (1 << (m-1));  
  3.     /*将1左移m-1位找到第m位,得到000...1...000 
  4.       n在和这个数做或运算*/  
  5. }  
int setBitToOne(int n, int m){
	return n | (1 << (m-1));
	/*将1左移m-1位找到第m位,得到000...1...000
	  n在和这个数做或运算*/
}

20.从低位到高位,将n的第m位置0

  1. int setBitToZero(int n, int m){  
  2.     return n & ~(1 << (m-1));  
  3.     /* 将1左移m-1位找到第m位,取反后变成111...0...1111 
  4.        n再和这个数做与运算*/  
  5. }  
int setBitToZero(int n, int m){
	return n & ~(1 << (m-1));
	/* 将1左移m-1位找到第m位,取反后变成111...0...1111
	   n再和这个数做与运算*/
}


另附一些对程序效率上没有实质提高的位运算技巧,一些也是位运算的常识(面试也许会遇到)

计算n+1

  1. -~n  
-~n

计算n-1

  1. ~-n  
~-n

取相反数

  1. ~n + 1;  
~n + 1;

另一种写法

  1. (n ^ -1) + 1;  
(n ^ -1) + 1;

if(x == a) x = b; if(x == b) x = a;

  1. x = a ^ b ^ x;  
x = a ^ b ^ x;

sign函数,参数为n,当n>0时候返回1,n<0时返回-1,n=0时返回0

  1. return !!n - (((unsigned)n >> 31) << 1);   
return !!n - (((unsigned)n >> 31) << 1); 


如果您知道实用的一行位运算技巧请留言,博主不胜感激,还有我总结的位运算难免有不健壮之处,请您多多批评

==================================================================================================

  作者:nash_  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址http://blog.csdn.net/nash_/article/details/8262185

===================================================================================================

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值