真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

【C語言練習(xí)】二進(jìn)制中1的個數(shù)-創(chuàng)新互聯(lián)

在這里插入圖片描述在這里插入圖片描述

成都創(chuàng)新互聯(lián)公司公司2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站制作、成都網(wǎng)站設(shè)計、外貿(mào)營銷網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元豐都做網(wǎng)站,已為上家服務(wù),為豐都各地企業(yè)和個人服務(wù),聯(lián)系電話:18980820575

目錄
  • 題目詳情:
  • 思路一:
  • 思路二:
  • 思路三:

題目詳情:

在這里插入圖片描述

思路一:

?拿到二進(jìn)制的每一位,看它是否等于 1 1 1,再定義一個計數(shù)器變量,如果等于 1 1 1,計數(shù)器變量就加 1 1 1。最終計數(shù)器的值就是 1 1 1 的個數(shù)。
?現(xiàn)在的問題就變成了—— 如何得到二進(jìn)制的每一位? 以十進(jìn)制數(shù)字 123 123 123 為例,通過123%10=3就能得到 3 3 3,不難發(fā)現(xiàn):只要用一個數(shù)除以它的進(jìn)制數(shù),最終的余數(shù)就是這個數(shù)最低位上的數(shù)字,因此如果要得到 2 2 2 首先要讓 2 2 2 來到最低位,只要去掉當(dāng)前最低位上的 3 3 3 , 2 2 2 就能來到最低位上。如何去掉最低位上的數(shù)字呢? 通過123/10=13就能把最低位上的 3 3 3 去掉??梢姡褐灰靡粋€數(shù)除以它的進(jìn)制數(shù),就能去掉該數(shù)當(dāng)前的最后一位數(shù)字。(這里指的是整數(shù)除法)因此我們只要不斷地重復(fù)上面的兩個步驟,就能都得到一個數(shù)上的每一位數(shù)字。二進(jìn)制數(shù)也同理。思路整理的差不多接下來就該通過代碼來實現(xiàn)了。

代碼實現(xiàn):

int NumberOf1(int a)
{int count = 0;//計數(shù)器
	while (a)
	{if (a % 2 == 1)//通過取模得到最低位上的數(shù)字
		{	count++;
		}
		a /= 2;//通過整數(shù)除法取出掉最低位上的數(shù)字
	}
	return count;
}

int main()
{int a = 0;
	scanf("%d", &a);
	int num = NumberOf1(a);
	printf("%d\n", num);
	return 0;
}

上述代碼缺陷:
?經(jīng)過測試發(fā)現(xiàn),上述代碼可以準(zhǔn)確計算出一個正整數(shù)二進(jìn)制位中 1 1 1 的個數(shù),當(dāng)參數(shù)是負(fù)數(shù)時,計算出來的結(jié)果,與我們希望的結(jié)果會有很大的差距。以 ? 1 -1 ?1 為例,理論上 ? 1 -1 ?1 的補碼是32個全 1 1 1 ,因此計算出來的結(jié)果應(yīng)該是32才對,但上面這段代碼計算出的結(jié)果是 0 0 0 ,為什么呢?結(jié)果是 0 0 0 說明if (-1 % 2 == 1)沒成立過,我們可以通過內(nèi)存窗口來看看-1 % 2的結(jié)果到底是什么,

在這里插入圖片描述
?結(jié)果是ff ff ff ff。內(nèi)存中存的是補碼,所以對應(yīng)的二進(jìn)制補碼就是 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111,int b說明b是一個有符號的的整型,因此前面二進(jìn)制的最高位是符號位,并且是 1 1 1 ,說明-1%2的結(jié)果是一個負(fù)數(shù),自然就不可能等于 1 1 1 了。我們發(fā)現(xiàn):只要是一個負(fù)數(shù),對 2 2 2 取模得到的結(jié)果就一定是一個負(fù)數(shù),就永遠(yuǎn)也不可能等于 1 1 1,如何解決這個問題呢?
?這里我們可以把形參設(shè)置成一個無符號的整型變量,此時問題就迎刃而解了。還是以 ? 1 -1 ?1 為例: ? 1 -1 ?1 在內(nèi)存中的補碼是 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 傳參的時候用一個無符號的整型變量a去接收 ,在這個無符號的整型變量a的眼里 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 就不再是什么 ? 1 -1 ?1 的補碼了,a認(rèn)為這就是一串普普通通的二進(jìn)制代碼,沒有什么所謂的符號位這些亂七八糟的東西。因此再用a%2得到的結(jié)果就不再可能是負(fù)數(shù)了,我們還是可以通過調(diào)試來一探究竟。

在這里插入圖片描述
?上圖中,我們把 ? 1 -1 ?1 賦值給一個無符號的的整型變量a,然后用a%2得到的結(jié)果是 1 1 1 ,并且也是無符號整型;用a/2得到 2147483647 2147483647 2147483647 ,這個很容易理解,因為 ? 1 -1 ?1 的補碼 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 在a的眼里就是一個平平無奇的二進(jìn)制序列,沒有符號位,這個二進(jìn)制序列轉(zhuǎn)換成十進(jìn)制就是: 4 , 294 , 967 , 295 4,294,967,295 4,294,967,295,除以 2 2 2 就得到 2147483647 2147483647 2147483647

在這里插入圖片描述
代碼修改:

int NumberOf1(unsigned int a)//把形參改成無符號整型,就對負(fù)數(shù)也適用了
{int count = 0;
	while (a)
	{if (a % 2 == 1)
		{	count++;
		}
		a /= 2;
	}
	return count;
}

int main()
{int a = 0;
	scanf("%d", &a);
	int num = NumberOf1(a);
	printf("%d\n", num);
	return 0;
}

?上面的代碼,在傳 ? 1 -1 ?1 的時候,計算出來的結(jié)果就是我們所期待的 32 32 32 了。到這里,思路一就結(jié)束了。接下來看另一種思路。

思路二:

?思路二的大體方向和思路一 一樣,得到二進(jìn)制序列的每一位,然后看其是否等于 1 1 1 。只不過思路二的實現(xiàn)方法與思路一不同,會比思路一容易一些,都是初學(xué)者不容易想出來。接下來就來整理一下思路二吧,首先我們還是希望得到二進(jìn)制的每一位,此時我們可以借助按位與(&)這個操作符來實現(xiàn),還記得按位與的計算過程嘛?對應(yīng)的兩個二進(jìn)制位都為 1 1 1 的時候出 1 1 1 ,其他全部出 0 0 0 ,因此,可以讓待求得二進(jìn)制序列按位與上 1 1 1 , 1 1 1 的二進(jìn)制序列為 00000000000000000000000000000001 00000000000000000000000000000001 00000000000000000000000000000001 ,此時待求的二進(jìn)制序列的最低位如果是 1 1 1 ,那1&1得到的結(jié)果就是 1 1 1 ,如果待求的二進(jìn)制序列的最低位是 0 0 0 ,那0&1得到的結(jié)果就是 0 0 0,我們發(fā)現(xiàn)任何一個二進(jìn)制只要與上 1 1 1 都會得到它自身。此時我們得到了二進(jìn)制序列的最低位,那它的第二位、第三位、第四位……呢?別忘了,我們還有一個移位操作符,我們可以利用移位操作符,讓二進(jìn)制序列往右移動,使得每一個二進(jìn)制位都能與上 1 1 1 ,這樣我們就能拿到二進(jìn)制序列的每一位了。大體思路捋的差不多了,接下來該上代碼了。

int NumberOf1(int a)
{int i = 0;
	int count = 0;
	for (i = 0; i< 32; i++)//最多只需右移31個二進(jìn)制位
	{if (((a >>i) & 1) == 1)//只有當(dāng)1 & 1結(jié)果才是1,讓a的二進(jìn)制位一直右移
		{	count++;
		}
	}
	return count;
}

int main()
{int a = 0;
	scanf("%d", &a);
	int num = NumberOf1(a);
	printf("%d\n", num);
	return 0;
}

?思路二也無需考慮什么正負(fù)數(shù),因為移位操作符和位操作符都是直接針對二進(jìn)制位來計算的,看完思路二我就只想說。但是別急,接下來的思路三才算得上是“王炸”

思路三:

?這里直接上方法,記住下面這個式子:n=n&(n-1)。舉個例子,以十進(jìn)制的 11 11 11 為例, 11 11 11 的二進(jìn)制是 1011 1011 1011 ,此時n=1011;,n-1=1010;,n&(n-1)=1010此時n就變成了: 1010 1010 1010 ,對比前面的n我們發(fā)現(xiàn)二進(jìn)制序列最右邊的 1 1 1 變成了 0 0 0 ,接著往下,n=1010;,n-1=1001;n&(n-1)=1000此時n就變成了 1000 1000 1000 對比第二個n二進(jìn)制序列最右邊的 1 1 1 又變成了 0 0 0,再往下看,n=1000;,n-1=0111;,n&(n-1)=0000此時n就變成了 0000 0000 0000 。不難發(fā)現(xiàn):n從最初的 1011 1011 1011 ,變成了現(xiàn)在的 0000 0000 0000 是把n=n&(n-1)這個式子執(zhí)行了 3 3 3 次,什么?3??這不就是 1011 1011 1011 這個二進(jìn)制序列里面 1 1 1 的個數(shù)嘛,其實這并非偶然,因為n=n&(n-1)這個式子每執(zhí)行一次,就會把當(dāng)前n這個二進(jìn)制序列里面最右邊的 1 1 1 去除掉,直到整個二進(jìn)制序列變成 0 0 0 ,分析的差不多了,接下來上代碼!

int NumberOf1(int n)
{int count = 0;
	while (n)//能變成全0的時候,就不用再執(zhí)行下面的式子了
	{n = n & (n - 1);
		count++;//記錄上面這個式子一共執(zhí)行了多少次
	}
	return count;
}

int main()
{int n = 0;
	scanf("%d", &n);
	int num = NumberOf1(n);
	printf("%d\n", num);
	return 0;
}

?哈哈,沒騙你吧,思路三才是最終的“王炸”

?好了,這道題的分享就到這里啦,如果你有更好的思路或者方法,歡迎在評論區(qū)或者私信,給我留言,拜拜咯!


在這里插入圖片描述

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


當(dāng)前文章:【C語言練習(xí)】二進(jìn)制中1的個數(shù)-創(chuàng)新互聯(lián)
標(biāo)題來源:http://weahome.cn/article/heejs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部