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

     我們知道在我們對一個數進行位運算的時候,是在這個數的補碼上進行的,對於補碼我們知道,正數的補碼是原碼,負數的補碼爲原碼除了最高位的符號位,取反,然後加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。完整代碼如下:

 

  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)也可以得到絕對值。所以可以對上面代碼優化下:

 

  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語句的時候),因此建議讀者記住該方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章