1. 程式人生 > 其它 >不使庫函式(abs)通過位運算實現取一個整數的絕對值

不使庫函式(abs)通過位運算實現取一個整數的絕對值

技術標籤:c語言補碼反碼二進位制

不使庫函式(abs)通過位運算實現取一個整數的絕對值

問題出自:2017年韓山師範學院本科插班生考試 第3題

  • image-20210211154114596

需要用到的知識點

  • 原碼、補碼、反碼
  • 負數轉2進位制
  • 位運算
  • 2進位制乘法(關係不大)

解題程式碼:

  • int myabs(int n)
    {
    	return n * ((n>>31<<1) +1);
    }
    
  • 整型變數 n 右移31位 左移1位 +1 乘 n

原碼

  • 正數的原碼就是它本身,符號位 為 0
  • 負數符號位為1,八位二進位制舉例:1000 1010 = (-10)10

反碼

  • 正數的反碼和原碼相同
  • 負數的反碼符號位置不變,其他按位取反,整數-10的反碼是:1111 0101

補碼

  • 正數的補碼和原碼一樣
  • 負數的補碼為反碼+1 整數-10的補碼是:1111 0110 這就是整數-10在計算機中的儲存形式

負數轉二進位制

  • 計算機中沒有直接做減法,是通過加法來實現的,所以負數在計算機中是由原碼的補碼+1得到的
  • 符號位為1,符號為不變
    • 原碼轉補碼:取反+1
    • 補碼轉原始碼:-1取反

位移運算

左移運算<<

  • 低位補零,高位溢位
  • 不溢位的情況下相當於乘2

右移運算>>

  • 邏輯右移&&算數右移
    • 對無符號數,右移時高位補零,低位溢位
    • 對於有符號數,原來是0,同上,原來是1(即負數),左邊移入0還是1,取決於計算機系統,有系統補0有系統補1,補 0 的稱為邏輯右移,補 1 的稱為算數右移
    • 舉例 >>1
      • 1011 0011
      • 0101 1001(邏輯右移)
      • 1101 1001(算數右移)
    • Visual C++和其他C編譯器採用算數右移,有符號數右移時,原符號位為1,左邊高位補1

二進位制乘法

  • 舉例:

  • image-20210211162902369

解題

  • //以-2為 n 舉例
    //n * ((n>>31<<1)+1)
    //-2*(-2>>31<<1)+1  
    
    
    1000000000 0000000000 0000000000 10
    //-2的原碼
      
    1111111111 1111111111 1111111111 01
    //-2的反碼
      
    1111111111 1111111111 1111111111 10
    //-2的補碼  -2反碼+1
    //這是-2 在計算機中的表示  以原始碼的補碼錶示
    1111111111 1111111111 1111111111 11 //-2 >> 31 1111111111 1111111111 1111111111 10 //<< 1 1111111111 1111111111 1111111111 11 //+1 //這是-1在計算機中的表現形式 //補碼轉原始碼:符號位不變,減1取反 1000000000 0000000000 0000000000 01 //-1 原碼 //-2 * -1 = 2 最後得出n的絕對值為2 //正數就不舉例了
部落格參考