使用位運算求整數的絕對值


一、整數的基礎知識

1. int在內存中占4個字節,32位。

2.int在內存中以補碼的形式表示。

1)正數的原碼、反碼、補碼都是一樣的。

2)負數的補碼=負數的原碼除符號位外取反,然后加1

所以,在內存中,-1和1的表示差別不僅僅在符號位。

 

二、右移運算符

 右移運算符指高位按符號位進行填充。即正數用0填充,負數用1填充。

因此,若定義int x,那么 x>>31,若x為正數,結果是0,若x為負數,結果是0Xffffffff,也就是-1的補碼。因為整數在內存中就是用補碼表示,所以,0Xffffffff就是-1。

 

三、異或運算符

異或可以理解為不進位加法,即1+1 = 0, 0+0=0,1+0=1。

由上可知,任意整數與0異或,結果還是整數本身,與0Xffffffff異或,則是將該整數連同符號位在內一並取反。

上面的知識是使用位運算求整數絕對值時需要用到的。下面再補充一些異或運算的其他知識。

 

異或運算的四個性質:

1)交換律

可任意交換運算因子的位置,結果不變。  即a^b = b^a

2)結合律

(a^b)^c  =  a^(b^c)

3)對於任何數x,都有x^x = 0, x^0 = x, 即同自己求異或為0,同0求異或為自己。

4)自反性 

連續和同一個因子做異或運算,最終結果為自己。

A^B^B = A^0 = A

 

四、使用位運算求整數的絕對值

原理:

負數的補碼原碼轉補碼是 除符號位取反加1,補碼轉原碼也是 除符號位取反加1。如果我們求出了一個負數的原碼,那么它的絕對值就是將這個原碼的符號位取反即可(將1取反為0)。

即:補碼轉原碼時,除符號位都取反了,原碼轉絕對值時,符號位被取反了,那么,將這兩次取反操作合在一起,即:對補碼的所有位取反,然后加1,可得到該補碼對應的負數的絕對值。

 

C語言代碼:

int abs(int a) { int iMask = a>>31; a = a^iMask-iMask; return a; } 

 

或者:

int abs(int a) { int iMask = a>>31; a = a^iMask;
  a = a-
iMask;
return a; }

 

代碼解析:

當a為正數時:第一步,iMask=0,第二步,a異或0,結果a還是本身,第三步,a-0,結果還是a。符合正數的絕對值是其本身,代碼成立。

當a為負數時

第一步,iMask=0Xffffffff,即-1的補碼,因為整數在內存中用補碼表示,所以iMask實際上就是-1;

第二步,a異或0Xffffffff,即連同符號位在內對a取反,此時,符號位1變成0,即負號變成正號。

第三步,a-iMask = a-(-1) = a+1,負數的補碼 = 除符號位外取反加1,第二步將符號位變為正號,完成了絕對值的過程,第三步此處完成了負數數字部分的轉變。這樣就成功求出了負數的絕對值。

 

 

 


免責聲明!

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



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