移位、位操作符的運用

打印整數二進制的奇數位和偶數位

  1. 提取所有的奇數位,如果該位是1,輸出1,是0則輸出0
  2. 以同樣的方式提取偶數位置
#include<stdio.h>
#include<windows.h>

#pragma warning(disable:4996)
void Printf(int a)
{
	int i = 0;
	for (i = 30; i >= 0;i-=2)//奇數位
	{
		if(a&(1 << i))
		{
			printf("1 ");
		}
		else
		{
			printf("0 ");
		}
	}
	printf("\n");
	for (i = 31; i > 0; i -= 2)//偶數位
	{
		printf("%d ", (a>>i)&1 );
	}
	printf("\n");
}
int main()
{
   int a=123;
   Printf(a);
   system("pause");
   return 0;
}

123 的二進制序列
a=0000 0000 0000 0000 0000 0000 0111 1011
0000 0000 0000 0000 0000 0000 0000 0001
打印最高位偶數位將 實則將a 移動31 之後的偶數位依次減二
打印最高位奇數位將 實則將a 移動30 之後的奇數位依次減二

第一種做法
printf("%d ", (a>>i)&1 );
將a 移動對應的i 位 與1 進行按位與 按照%d 打印就可以,因爲按位與出來的結果前31 位全是0 最後一位不是 0 就是1 ,可以用十進制的格式打印。

如果將1 進行對應的移位操作,printf("%d ", a&(1<<i )); 並且還按照十進制格式輸出
出出現如下清況

a=0000 0000 0000 0000 0000 0000 0111 1011
0000 0000 0000 0000 0000 0000 0100 0000
此時輸出的結果就是 100 0000轉爲十進制 爲64
因此不建議對1 進行移位操作,就算是對1 進行移位操作也不能用十進制的方式輸出。
// if(a&(1 << i))
{
printf("1 ");
}
else
{
printf("0 ");
}

交換兩個變量(不創建臨時變量)

#include<stdio.h>
#include<windows.h>
#pragma warning(disable:4996)
int main()
{
	//不允許創建臨時變量,交換兩個整數的內容
	int a = 0;
	int b = 0;
	printf("請輸入兩個要交換的變量:>\n");
	scanf("%d %d", &a, &b);
	
	a = a^b;
	b = a^b;
	a ^=b;
	printf("a=%d,b=%d\n", a, b);
	system("pause");
	return 0;
}

a = a^b 異或操作之後 此時把 a 想象成一個密碼,與b按位異或後可以解出 a 同理 與a按位異或後可以解出 b

統計二進制中1的個數

/*
方法一:
思路:
循環進行以下操作,直到n被縮減爲0:

  1. 用該數據模2,檢測其是否能夠被2整除
  2. 可以:則該數據對應二進制比特位的最低位一定是0,否則是1,如果是1給計數加1
  3. 如果n不等於0時,繼續1
    */

int count_one_bit(int n)
{
	int count = 0;
	while(n)
	{
		if(n%2==1)
			count++;
		n = n/2;
	}
	return count;
}

上述方法缺陷:主要的問題就是對負數沒有辦法進行運算
進行了大量的取模以及除法運算,取模和除法運算的效率本來就比較低。

方法二思路:
一個int類型的數據,對應的二進制一共有32個比特位,可以採用位運算的方式一位一位的檢測,具體如下

int count_one_bit(unsigned int n)
{
	int count = 0;
	int i = 0;
	for(i=0; i<32; i++)
	{
		if(((n>>i)&1) == 1)
			count++;
	}
	return count;
}

方法二優點:用位操作代替取模和除法運算,效率稍微比較高
缺陷:不論是什麼數據,循環都要執行32次

方法三:
思路:採用相鄰的兩個數據進行按位與運算

可以觀察下:此種方式,數據的二進制比特位中有幾個1,循環就循環幾次,而且中間採用了位運算,處理起來比較高效

int count_one_bit(int n)
{
	int count = 0;
	while(n)
	{
		n = n&(n-1);
		count++;
	}
	return count;
}

每次在最右的1設置一個flag的話,

當它(i)它前一位(i-1)進行&操作時,對flag左邊的1是沒有影響的,每次得到的結果,就會將flag位置及右邊所有的數置爲0.指路一個詳解

求兩個數二進制中不同位的個數

思路:

  1. 先將m和n進行按位異或,此時m和n相同的二進制比特位清零,不同的二進制比特位爲1
  2. 統計異或完成後結果的二進制比特位中有多少個1即可
#include <stdio.h>
int calc_diff_bit(int m, int n)
{
	int tmp = m^n;
	int count = 0;
	while(tmp)
	{
		tmp = tmp&(tmp-1);
		count++;
	}
	return count;
}


int main()
{
 int m,n;
 while(scanf("%d %d", &m, &n) == 2)
 {
     printf("%d\n", calc_diff_bit(m, n));
 }
 return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章