一、什麼是二進位制

眾所周知,計算機存取一個數都是以0,1的方法存取的。

比如一個整形的1,在記憶體裡就是00000000 00000000 00000000 00000001

那麼-1呢,不會以為是10000000 00000000 00000000 00000001

我告訴你,這不對。

計算機存取資料是以二進位制補碼的形式儲存的

正數的原碼、反碼和補碼是一樣的

負數卻不是

-1的原碼是                                         10000000 00000000 00000000 00000001

反碼 (符號位不變,其他按位取反)11111111 11111111 11111111 11111110

補碼(反碼基礎上+1)                      11111111 11111111 11111111 11111111

二、這次,就讓我們來求一個 int型(32個BIT位)的正數中二進位制1的個數

(1)基礎版->利用數學方法求解

計算方法:

基礎版程式碼塊:

#include<stdio.h>
int  count_one_bits(int value)
{
	int count = 0;
	while( value != 0 )
	{
		if(value%2 == 1)
			count++;
		value /= 2;
	}
	return count; 
}
int main()
{	
	unsigned value = 0;
	int count = 0;
	printf("請輸入一個正整數:");
	scanf("%d",&value);
	count = count_one_bits(value);
	printf("這個數二進位制的1有%d個",count);
	return 0;
}

解析:

好了,程式碼在這塊,執行一下如何?

如果你真的運行了的話,除了試試正數之外,還應該試試負數 

你試試-1。程式不能輸出32吧。

當然了,你讓-1%2?

(2)強化版->運用右移操作符">>"

方法:

強化版程式碼塊:

#include<stdio.h>
int main()
{
 int value = 0;
 int count = 0;
 printf("請輸入一個整數:");
 scanf("%d",&value);
 int i = 0;
 for( i = 0; i<32 ;i++)
 { 
  if(value&1==1) 
   count++; 
  value = value >> 1;
 }
 printf("count = %d",count);
 return 0;
}

解析:

不錯,負數可以計算了,已經達到我們想要的目的

可是再仔細看一看,不管是幾她都要迴圈32次!

可不可以再優化呢?

(3)高階版->利用value = (value & (value - 1))

方法:

 

高階版程式碼塊:

#include<stdio.h>
int main()
{
	int value = 0;
	int count = 0;
	printf("請輸入一個整數:");
	scanf("%d",&value);
	while(value != 0)
	{	
		count++; 
		value = (value & (value-1)); 
	}
	printf("count = %d",count);
	return 0;
}

解析:

如果這幾個剛剛好才能看懂的話,

那麼你寫出這樣的程式碼,就可以了。

(4)機智如我版->隱式強制型別轉換(int 轉為 unsigned)

方法:

“機智如我版”程式碼塊:

#include<stdio.h>
int  count_one_bits(unsigned int value)
{
	int count = 0;
	while( value != 0 )
	{
		if(value%2 == 1)
			count++;
		value /= 2;
	}
	return count; 
}
int main()
{	
	unsigned value = 0;
	int count = 0;
	printf("請輸入一個整數:");
	scanf("%d",&value);
	count = count_one_bits(value);
	printf("這個數二進位制的1有%d個",count);
	return 0;
}

然而,高階版並不是最優的。

什麼?感覺還不夠深?

偷偷給我塞一塊錢我告訴你偷笑