位操作之求絕對值

今天繼續學習了位操作,用位操作實現求一個數的絕對值:
對於一個整數a,如果是個正數就直接返回,但是如果是個負數呢?應該取反再返回,比如-5取反後應該是+5,然後返回。
在計算機中數都是用二進制來表示的,就是一串的0和1組合:
例如5的二進制表示爲:0000 0101,
-5該如何表示,應該用補碼來表示,就是,+5的二進制先按位取反,然後加1,如下:
先按位取反得: 1111 1010, 然後加1
加1以後爲: 1111 1011 最高位表示符號 0位正,1爲負
所以,我們求一個數的絕對值的時候,對於int(4字節)我們可以先把所求的數右移31位,求的改數的符號位,如果符號位爲0,那麼該數是整數,直接返回;如果是1,那麼該數是負數,就按上面所說的,先按位取反,然後加1,返回。

對於移位操作來說,有算術移位和邏輯移位兩種。對於左移來說沒有區別,就是後面補0;但是對於右移來說不一樣,算術右移是補符號位,就是說正數補0,但是負數要補符號位的話是1,這個要看系統了。而邏輯移位就是補0.
對於位操作來說,他們在c中運算優先級別比較低,應該儘量用括號()來保證運算順序的正確性。

#include<stdio.h>

int my_abs(int a)
{
    int i ;
    i = a>>31;//右移31位取得符號位
    if(i == 0)//如果符號位是0,是正數,返回a
    return a;
    else//如果不是0
    return (~a+1);//返回(~a+1)就是a先按位取反,然後加1
}
int main()
{
    int k =-100;
    printf("%d\n",my_abs(k));

    return 0;
}

第二種方法:
用異或運算。異或就是說如果對應的二進制位不同,運算結果就是1,如果相同就爲0:
1^1 = 0; 1^0=1;0^0=0。我們也可以看出,任何數與0異或是它本身,與它本身異或結果是0:就是說對於一個數a來說,下面的運算式正確的:a^0 = a;a^a = 0;
再說一下一個數a,如果與-1(負1)異或結果會是什麼.我們可以先看一下+1和-1怎麼表示:
+1 = 0000 0001;
-1 = 1111 1110 +1 =1111 1111;
我們可以看到-1就是二進制的所有位都是1.
我們再看看前面的異或運算:1^1 = 0; 0^1 = 1;所以一個單獨的位和1異或就是把該位取反。
因爲 -1 就是所有二進制位爲1的數。所以一個數和 -1 異或的話,實際上就是 把該數 按位取反。
比如 5 = 0000 0101;

          5  = 0 0 0 0       0 1 0 1
  ^     -1 =   1 1 1 1       1 1 1 1
  -------------------------------------
    =          1 1 1 1       1 0 1 0(已經按位取反了)

所以我們也可以用異或的方法求絕對值,不用任何庫函數和判斷語句。

#include<stdio.h>


int my_abs2(int a)
{
    int i ;
    i = a>>31;//取得符號位
    return ((a^i) -i);//如果i是0的話,那麼(a^i)-i相當於(a^0)-0=a-0=a;
                      //如果i是-1的話,那麼(a^i)-i相當於(a^-1)-(-1)=(~a)+1,就和上一例一樣了
}
int main()
{
    int k =-100;
    //printf("%d\n",my_abs(k));
    printf("--abs2----------------------------\n");
    printf("%d\n",my_abs2(-1000));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章