1. 程式人生 > >位運算☞二進位制神祕面紗

位運算☞二進位制神祕面紗

二進位制:

       二進位制是計算技術中廣泛採用的一種數制二進位制數據是用0和1兩個數碼來表示的數。它的基數為2,進位規則是“逢二進一”,借位規則是“借一當二”,由18世紀德國數理哲學大師萊布尼茲發現。當前的計算機系統使用的基本上是二進位制系統,資料在計算機中主要是以補碼的形式儲存的。計算機中的二進位制則是一個非常微小的開關,用“開”來表示1,“關”來表示0。20世紀被稱作第三次科技革命的重要標誌之一的計算機的發明與應用,因為數字計算機只能識別處理由‘0’.‘1’符號串組成的程式碼。其運算模式正是二進位制。19世紀愛爾蘭邏輯學家喬治布林對邏輯命題的思考過程轉化為對符號"0''.''1''的某種代數演算,二進位制是逢2進位的進位制。0、1是基本

算符。因為它只使用0、1兩個數字符號,非常簡單方便,易於用電子方式實現。

位運算:

       程式中的所有數在計算機記憶體中都是以二進位制的形式儲存的。位運算就是直接對整數在記憶體中的二進位制位進行操作。比如,and運算本來是一個邏輯運算子,但整數與整數之間也可以進行and運算。舉個例子,6的二進位制是110,11的二進位制是1011,那麼6 and 11的結果就是2,它是二進位制對應位進行邏輯運算的結果(0表示False,1表示True,空位都當0處理)。

位運算基礎:
& 
按位與
如果兩個相應的二進位制位都為1,則該位的結果值為1,否則為0


按位或
兩個相應的二進位制位中只要有一個為1,該位的結果值為1

按位異或
若參加運算的兩個二進位制位值相同則為0,否則為1

void swap(long int &a,long int &b)
{
    a = a^b;          
    b = a^b;        
    a = a^b;        
}                 
void swap(long int &a,long int &b)
{
     a = a+b;
     b = a-b;
     a = a-b;
}


取反
~是一元運算子,用來對一個二進位制數按位取反,即將0變1,將1
<< 
左移
用來將一個數的各二進位制位全部左移N位,右補0
>> 
右移
將一個數的各二進位制位右移N位,移到右端的低位被捨棄,對於無符號數, 高位補0

使用技巧_

技巧一:用於消去x的最後一位的1

x & (x-1) 

x = 1100          //二進位制1100,12
x-1 = 1011        //減法運算,減1,二進位制1011,11
x & (x-1) = 1000  //x&(x-1)運算,去掉二進位制中最後一個1,二進位制1000,8

 

1.1 用O(1)時間檢測整數n是否是2的冪次.

  • 思路解析:N如果是2的冪次,則N滿足兩個條件。 
  • (1) N>0 
  • (2) N的二進位制表示中只有一個1 
  • 一位N的二進位制表示中只有一個1,所以使用N&(N-1)將唯一的一個1消去。 
  • 如果N是2的冪次,那麼N&(N-1)得到結果為0,即可判斷。

1.2.計算在一個 32 位的整數的二進位制表示中有多少個 1.

  • 思路解析:
  • 由 x & (x-1) 消去x最後一位知。迴圈使用x & (x-1)消去最後一位1,計算總共消去了多少次即可。

1.3.將整數A轉換為B,需要改變多少個bit位

  • 思路解析 :
  • 思考將整數A轉換為B,如果A和B在第i(0<=i<32)個位上相等,則不需要改變這個bit位,如果在第i位上不相等,則需要改變這個bit位。所以問題轉化為了A和B有多少個bit位不相同。聯想到位運算有一個異或操作,相同為0,相異為1,所以問題轉變成了計算A異或B之後這個數中1的個數。

技巧二 :使用二進位制進行子集列舉

1.1 給定一個含不同整數的集合,返回其所有的子集
樣例:如果 S = [1,2,3],有如下的解: 
[ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2] ]

思路:使用一個正整數二進位制表示的第i位是1還是0,代表集合的第i個數取或者不取。所以從0到2^n-1總共2^n個整數,正好對應集合的2^n個子集。

S = {1,2,3}
N bit Combination
0 000 {}
1 001 {1}
2 010 {2}
3 011 {1,2}
4 100 {3}
5 101 {1,3}
6 110 {2,3}
7 111 {1,2,3}

技巧三:找出現一次的數字

a^b^b=a

1.1 應用一 陣列中,只有一個數出現一次,剩下都出現三次,找出出現一次的。
問題
Given [1,2,2,1,3,4,3], return 4

解題思路
因為只有一個數恰好出現一個,剩下的都出現過兩次,所以只要將所有的數異或起來,就可以得到唯一的那個數。

int one_exsit(int *arr ,int len)
{
    int ans = 0;
    for(int i=0;i<len;i++){
        ans^=arr[i];
    }
   return ans;
}

補充:

如果兩個不同長度的資料進行位運算時,系統會將二者按右端對齊,然後進行位運算。

以“與”運算為例說明如下:我們知道在C語言中long型佔4個位元組,int型佔2個位元組,如果一個long型資料與一個int型資料進行“與”運算,右端對齊後,左邊不足的位依下面三種情況補足,

(1)如果整型資料為正數,左邊補16個0。

(2)如果整型資料為負數,左邊補16個1。

(3)如果整形資料為無符號數,左邊也補16個0。

如:long a=123;int b=1;計算a& b。

如:long a=123;int b=-1;計算a& b。

如:long a=123;unsigned intb=1;計算a & b。