位操作符、移位操作符與位運算

位運算是把數字用二進制表示之後,對每一位上0或者1的運算。二進制及其位運算是現代計算機學科的基石,很多底層的技術也都離不開位運算,由於在我們日常生活中習慣了十進制,很多人看到二進制以及位運算都感到很難適應,接下來我們一起討論一下移位操作符和位操作符以及位運算。

移位操作符

<< 左移操作符
在這裏插入圖片描述
>> 右移操作符
在這裏插入圖片描述

位操作符

& 按位與(二進制位)
| 按位或(二進制位)
^ 按位異或 相同爲0相異 相異爲1(二進制位)
注意區分邏輯與 &&(兩真爲1) 和邏輯或 ||(兩假爲0)

我們來看一道面試題(360):

#include <stdio.h>
int main()
{
	int i = 0,a = 0,b = 2,c = 3,d = 4;
	i = a++ && ++b && d++;
	//i = a++ || ++b || d++;
	printf("a=%d b=%d c=%d d=%d",a,b,c,d);
	return 0;
}

運行結果:

a=1 b=2 c=3 d=4

解析:
邏輯&&運算一旦左邊爲假後面便不再運算,本題a=0先發生作用使&&左邊爲假b,c,d的值不再變化,a再++變爲1 輸出。

位運算

其實二進制的位運算並不是很難掌握,因爲位運算總共只有上述的五種,&,|,^,>>,<<。
注:下表的0 1均在二進制環境中
在這裏插入圖片描述
我們通過幾個例子來熟悉掌握位運算吧!

題目:實現一個函數,輸入一個整數,輸出該數二進制表示中1的個數(劍指offer面試題)

解法一:(可能引起死循環的解法)

  • 基本思路:先將這個數二進制表中最後一位與1做&運算判斷最後一位的值,然後再將這個數右移一位即可判斷倒數第二位的值,以此類推,定義計數器count,&的結果爲1則count++,直到這個數爲0跳出while循環,輸出count。
int Count(int n)
{
	int count = 0;
	while (n)
	{
		if (n & 1)
			count++;
			
		n = n >> 1;
	}
	return count;
}

注意:雖然右移一位和÷2在數學上等價,但除法效率比右移操作低得多,所以不能更換右移操作爲除法。
缺陷:如果輸入負數,右移過程中高位始終補1,最終陷入死循環。

解法二:(常規解法)

  • 基本思路:爲了避免死循環可以不移動輸入的n,去左移與n進行&運算的1,直到flag的二進制變爲全0,跳出while,輸出count。
int Count(int n)
{
	int count = 0;
	int flag = 1;
	while (flag)
	{
		if (n & flag)
			count++;
			
		flag = flag << 1;
	}
	return count;
}

缺陷:不論1的個數爲多少,該程序都會循環32次

解法三:(給面試官帶來驚喜的解法)

  • 基本思路:把一個整數n減去1,都是把它二進制序列最右邊的1變爲0,而左邊的其他位保持不變,右邊的0變爲1。再將n和n-1做&運算,下一個1之前的二進制序列全都變爲0。n中有幾個1就進行幾次&運算,大大提高了程序的效率。
int Count(int n)
{
	int count = 0;
	while (n)
	{
		n = n&(n - 1);//每次&都是最後一個爲1的位變爲0
		count++;
	}
	return count;
}

亮點:有多少個1就循環多少次
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章