位運算總結 (左移、右移、按位與、按位或、按位非、按位異或)


刷題的時候碰見了一些位運算,有印象但是對它們的算法實際用處不了解,於是就再次回顧一下其表現特征,歸納一下了解到的知識點~

參考:

位運算(按位與、按位或、異或)

按位異或運算 (正數異或負數) 、按位非(~)

15種位運算的妙用,你都知道嗎?

規則:

正數:反碼、原碼、補碼相同,符號位為0

負數:反碼,符號位為1,數值位按位取反

補碼,反碼+1

已知負數補碼求原碼:符號位不變,數值位減1再取反; 或者,符號位不變,數值位取反后再加1

所有參與運算的都是以補碼形式進行的 結果也是補碼 因此也需要將補碼轉換成為原碼的形式存在
左移 <<
  • 左移的特征:用來倍增(乘2^n,n為移動的數值)。
NSLog(@"1左移-->%d",1<<1);//0001 -->2
NSLog(@"2左移-->%d",2<<1);//0010 -->4
NSLog(@"3左移-->%d",3<<1);//0011 -->6
NSLog(@"4左移-->%d",4<<1);//0100 -->8
NSLog(@"5左移-->%d",5<<1);//0101 -->10
NSLog(@"6左移-->%d",6<<1);//0110 -->12
NSLog(@"7左移-->%d",7<<1);//0111 -->14
NSLog(@"8左移-->%d",8<<1);//1000 -->16
右移 >>
  • 右移的特征:用來整除(除2^n,n為移動的數值)並舍去余數。
NSLog(@"1右移-->%d",1>>1);//0001 -->0
NSLog(@"2右移-->%d",2>>1);//0010 -->1
NSLog(@"3右移-->%d",3>>1);//0011 -->1
NSLog(@"4右移-->%d",4>>1);//0100 -->2
NSLog(@"5右移-->%d",5>>1);//0101 -->2
NSLog(@"6右移-->%d",6>>1);//0110 -->3
NSLog(@"7右移-->%d",7>>1);//0111 -->3
NSLog(@"8右移-->%d",8>>1);//1000 -->4
按位與 &
  • 與的特征:只有兩個數的二進制同時為1,結果才為1,否則為0
  • 與1運算,可以判斷奇偶性。 A&1 = 0 (偶數). A&1 = 1 (奇數)
NSLog(@"按位與-->%d",0&0);//0000 & 0000 0
NSLog(@"按位與-->%d",0&1);//0000 & 0001 0
NSLog(@"按位與-->%d",1&0);//0001 & 0000 0
NSLog(@"按位與-->%d",1&1);//0001 & 0001 1
NSLog(@"按位與-->%d",2&2);//0010 & 0010 2
NSLog(@"按位與-->%d",4&4);//0100 & 0100 4
NSLog(@"按位與-->%d",-2&2);// 2
NSLog(@"按位與-->%d",-4&4);// 4
NSLog(@"-->%d",-7&7);//1

//判斷奇偶性
NSLog(@"按位與-->%d",0&1);//0
NSLog(@"按位與-->%d",1&1);//1
NSLog(@"按位與-->%d",2&1);//0
NSLog(@"按位與-->%d",3&1);//1
/*
  -2 和 2為例:
  1000 0000 0000 0010 -2原碼
  1111 1111 1111 1101 -2反碼
  1111 1111 1111 1110 -2補碼
  0000 0000 0000 0010 2 結果為2
*/
按位或 |
  • 或的特征:數值位只要兩個數中的一個為1,結果就為1。
NSLog(@"按位或-->%d",0|0);//0000 & 0000 0
NSLog(@"按位或-->%d",0|1);//0000 & 0001 1
NSLog(@"按位或-->%d",1|0);//0001 & 0000 1
NSLog(@"按位或-->%d",1|1);//0001 & 0001 1
NSLog(@"按位或-->%d",2|2);//0010 & 0010 2
NSLog(@"按位或-->%d",4|4);//0100 & 0100 4
NSLog(@"按位或-->%d",-2|2);// -2
NSLog(@"按位或-->%d",-4|4);// -4
/*
 -2 和 2
 1000 0000 0000 0010 原碼
 1111 1111 1111 1101 反碼
 1111 1111 1111 1110 補碼
 0000 0000 0000 0010 2補碼
 1111 1111 1111 1110 結果為補碼,如果是負數需要轉成原碼
 1111 1111 0000 0001 符號位不變,取反
 1111 1111 0000 0010 +1 為-2
*/
按位非 ~
  • 非的特征:按位取反 (最終表現為:先加1后取反,按照這個特性,數學用途可以歸納為求相反數:~A + 1)
NSLog(@"0按位非-->%d",~0);//0000 -1
NSLog(@"1按位非-->%d",~1);//0000 -2
NSLog(@"2按位非-->%d",~2);//0010 -3
NSLog(@"3按位非-->%d",~3);//0010 -4
NSLog(@"4按位非-->%d",~4);//0100 -5
NSLog(@"-2按位非-->%d",~-2);//  1
NSLog(@"-4按位非-->%d",~-4);//  3
        
/*
 0000 0000 0000 0000 0
 1111 1111 1111 1111 按位取反
 1111 1111 0000 0001 負數,符號位不變,取反+1 結果為-1

 1111 1111 0000 0010 -2
 1111 1111 1111 1110 -2補碼
 0000 0000 0000 0001 取反,正數,結果為1

 1111 1111 0000 0100 -4
 1111 1111 1111 1100 -4補碼(取反+1)
 0000 0000 0000 0011 3

 */
按位異或 ^
  • 異或的特征:參加運算的兩個數,如果兩個相應位為"異"(值不同),則該位結果為1,否則為0。
  • 任意數和自身異或結果為0,用於置0
  • 可以判斷兩個數是否相等,if((A^B ) == 0)
  • 0和任意數異或結果還是其本身。
  • 交換兩個數,a = a^b;b = b^a;a = a^b;
NSLog(@"按位異或-->%d",0^0);//0
NSLog(@"按位異或-->%d",0^1);//1
NSLog(@"按位異或-->%d",1^2);//3
NSLog(@"按位異或-->%d",-2^1);//-1
NSLog(@"按位異或-->%d",-3^-2);//3
/*
 0^1
 0000 0000 0000 0000 0
 0000 0000 0000 0001 1
 0000 0000 0000 0001 1
 1^2
 0000 0000 0000 0001 1
 0000 0000 0000 0010 2
 0000 0000 0000 0011 3
 -2^1
 1111 1111 0000 0010 -2 原碼
 1111 1111 1111 1110 -2補碼(取反+1)
 0000 0000 0000 0001 1
 1111 1111 1111 1111 符號位為負數,求其原碼
 1111 1111 0000 0001 -1(取反+1)
 -3^-2
 1111 1111 0000 0011 -3原碼
 1111 1111 1111 1101 -3補碼
 1111 1111 1111 1110 -2補碼
 0000 0000 0000 0011 3
 */

位運算總結:

1. 整數的平均值

對於兩個整數x,y,如果用 (x+y)/2 求平均值,會產生溢出,因為 x+y 可能會大於INT_MAX,但是我們知道它們的平均值是肯定不會溢出的,我們用如下算法:

int average(int x, int y)   //返回X,Y 的平均值
{   
     return (x&y)+((x^y)>>1);
}

2. 判斷一個整數是不是2的冪,對於一個數 x >= 0

boolean power2(int x)
{
    return ((x&(x-1))==0)&&(x!=0);
}

3. 用位運算符交換兩個整數

void swap(int x , int y)
{
    x ^= y;
    y ^= x;
    x ^= y;
}

4. 計算絕對值

int abs( int x )
{
  int y ;
  y = x >> 31 ;
  return (x^y)-y ;        //or: (x+y)^y
}

5. 求相反數

x 的 相反數

(~x+1)

6.判斷奇偶性

a&1   = 0 偶數
a&1   = 1 奇數


免責聲明!

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



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