用位运算求一个数的绝对值

     我们知道在我们对一个数进行位运算的时候,是在这个数的补码上进行的,对于补码我们知道,正数的补码是原码,负数的补码为原码除了最高位的符号位,取反,然后加1。把补码转换成原码的时候,正数还是原码,负数时把补码除了符号位取反然后加1(我们可以发现如果这时候连符号位也求反,然后加1,与以前不同的只是少了一个符号位,现在实际上就是这个数的绝对值)。所以我们可以得到对一个负数求绝对值的表达式为

  1. int SignReversal(int a)  
  2. {  
  3.     return ~a + 1;  
  4. }

那么由这些知识我们可以很快地得到求一个数的绝对值的表达式:

先移位来取符号位,int i = a >> 31;要注意如果a为正数,i等于0,为负数,i等于-1。然后对i进行判断——如果i等于0,直接返回。否之,返回~a+1。完整代码如下:

 

[cpp] view plaincopy
 
  1. //by MoreWindows( http://blog.csdn.net/MoreWindows )  
  2. int my_abs(int a)  
  3. {  
  4.     int i = a >> 31;  
  5.     return i == 0 ? a : (~a + 1);  
  6. }  

 

现在再分析下。对于任何数,与0异或都会保持不变,与-1即0xFFFFFFFF异或就相当于取反。因此,a与i异或后再减i(因为i为0或-1,所以减i即是要么加0要么加1)也可以得到绝对值。所以可以对上面代码优化下:

 

[cpp] view plaincopy
 
  1. //by MoreWindows( http://blog.csdn.net/MoreWindows )  
  2. int my_abs(int a)  
  3. {  
  4.     int i = a >> 31;  
  5.     return ((a ^ i) - i);  
  6. }  

而且有些笔面试题就要求这样做(比如不让用if语句的时候),因此建议读者记住该方法

 

posted @ 2013-08-04 20:32  jlins  阅读(5441)  评论(0编辑  收藏  举报