用位運算求一個數的絕對值


     我們知道在我們對一個數進行位運算的時候,是在這個數的補碼上進行的,對於補碼我們知道,正數的補碼是原碼,負數的補碼為原碼除了最高位的符號位,取反,然后加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語句的時候),因此建議讀者記住該方法

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM